【问题标题】:Translate Javascript if/else to Ramda cond issue将 Javascript if/else 转换为 Ramda cond 问题
【发布时间】:2017-02-22 10:54:19
【问题描述】:

我发现 if/else 逻辑检查后的处理有些问题。举个例子吧。

基本配置

const result = {
  data: 1,
  state: {
    pass: 'N'
  }
}

对于JS if/else检查,逻辑检查后不显示日志

function checking() {
  if(result.state.pass !== 'Y') {
    return result;
  }

  console.log("Should not appear the log")
}

checking()

然后,我尝试使用 Ramda cond 函数对其进行翻译

function checking() {
  R.cond([
    [
      R.compose(R.not, R.equals('Y'), R.prop('pass'), R.prop('state')),
      (res) => res
    ]
  ])(result)

  console.log("Should not appear the log")
}

checking()

但是,日志出现在 Ramda cond 示例中。我可以知道吗

  • 有什么问题吗?

  • 我可以在示例中增强什么?

谢谢。

【问题讨论】:

    标签: if-statement ramda.js


    【解决方案1】:

    更新:我最初读到这篇文章是关于日志应该何时显示的。


    我的建议是这样的:

    const checking = R.when(
      R.compose(R.equals('Y'), R.path(['state', 'pass'])),
      (res) => {console.log("Should not appear in the log"); return res;}
    )
    

    这是我从你的代码中得到的:我的第一步是修复cond的使用:

    const result1 = {data: 1, state: {pass: 'N'}}
    const result2 = {data: 2, state: {pass: 'Y'}}
    
    const checking = R.cond([
      [
        R.compose(R.not, R.equals('Y'), R.prop('pass'), R.prop('state')),
        R.identity
      ],
      [
        R.T, 
        (res) => {console.log("Should not appear in the log"); return res;}
      ]
    ])
    
    checking(result1); 
    //=> {data: 1, state: {pass: 'N'}} 
    checking(result2);
    // logs "Should not appear in the log
    //=> {data: 2, state: {pass: 'Y'}}
    

    注意cond 最像switch 语句:它接受一组条件结果对并返回一个函数,该函数将其参数传递给每一对,直到找到一个条件为真,然后返回调用其结果的结果。因此对于第二个条件,我们只检查R.T,这是一个始终返回true 的函数,并使用identity 来返回输入。

    这个新函数现在接受 result 对象并原封不动地返回它,如果它与初始测试不匹配,则会将消息记录到控制台。


    但这不是结束。这段代码可以重构。

    这是我将应用的一个简单修复:

    const checking = R.cond([
      [
        R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
        R.identity
      ],
      [
        R.T, 
        (res) => {console.log("Should not appear in the log"); return res;}
      ]
    ])
    

    这只是从compose(prop('pass'), prop('state')) 更改为path(['state', 'pass'])。这是一个小调整,但我认为这更清洁。


    下一个变化更具实质性。

    const checking = R.ifElse(
      R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
      R.identity,
      (res) => {console.log("Should not appear in the log"); return res;}
    )
    

    当我们有一个只有两个分支的cond 语句,而第二个语句在R.T 上进行测试时,我们可以用ifElse 更清楚地写出来。这需要一个条件和两个结果,一个用于条件通过,一个用于条件失败。


    这可能是您想要的,特别是如果您最终计划在失败情况下做一些不同的事情。但如果你不是,并且你真的只需要一个结果,那么R.unless 提供了对ifElse 的进一步简化,对于那些第二个结果只是传递的情况:

    const checking = R.unless(
      R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
      (res) => {console.log("Should not appear in the log"); return res;}
    )
    

    unless 只是检查条件并在条件为假时运行结果,如果为真则原封不动地返回输入。


    但是我们也可以通过从unless 切换到when 来移除not

    const checking = R.when(
      R.compose(R.equals('Y'), R.path(['state', 'pass'])),
      (res) => {console.log("Should not appear in the log"); return res;}
    )
    

    我可能会把它留在那里,尽管为了清楚起见,我可能会考虑一个 log 函数。

    所有这些都可以在 Ramda REPL 上获得(包括带有 log 函数的最终版本)。

    【讨论】:

      【解决方案2】:

      您忘记添加返回语句。

      const result = {
        data: 1,
        state: {
          pass: 'N'
        }
      }
      
      function checking() {
        // Need to add return statement below
        return R.cond([
          [
            R.compose(
              R.not, 
              R.equals('Y'), 
              R.prop('pass'), 
              R.prop('state')),
            (res) => res
          ]
        ])(result)
      
        console.log("Should not appear the log")
      }
        
      checking() 
      <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.min.js"></script>

      【讨论】:

      • 这与原来的功能不同:登录“Y”,否则不登录。 (console.log 语句不会被击中,因为它位于 return 之后。)
      猜你喜欢
      • 2019-04-15
      • 1970-01-01
      • 2012-03-08
      • 2021-08-30
      • 2013-05-01
      • 2019-04-09
      • 2014-04-13
      • 2019-02-25
      相关资源
      最近更新 更多