【问题标题】:Ruby - cleanest way to return a value if truthy, or execute arbitrary codeRuby - 如果真实,则返回值或执行任意代码的最干净的方法
【发布时间】:2015-10-27 13:53:19
【问题描述】:

我正在用 Ruby 编写一些代码,在给定方法调用的输出值 foo 时,我想:

  • 如果foo 为真,则返回foo
  • 如果foo 为假,则记录错误并返回默认值。

实现这一点的最简单天真的方法可能是:

foo = procedure(input)

if foo
  foo
else
  log_error
  default
end

但这感觉过于冗长,因为foo重复了三遍,而且这种风格非常必要。

最干净、最惯用的写法是什么?

(性能很重要——让我们假设foo 在绝大多数情况下都是真实的。)

【问题讨论】:

    标签: ruby performance idioms


    【解决方案1】:

    以 Ruby 的 Perl 传统为生:

    foo = procedure(input) and return foo
    log_error
    default
    

    【讨论】:

      【解决方案2】:

      这是 Ruby 的匿名块实际上有用的罕见情况:

      foo = procedure(input) || begin
        log_error
        default
      end
      

      【讨论】:

      • 是的!为了整个社区的利益,我接受得票最多的答案可能是最有意义的,但这正是我个人所寻找的。我刚刚对此进行了测试,看起来您也可以在没有分配的情况下编写它。我不知道你可以在 Ruby 中做到这一点。出于好奇,是否可以使用{ ... } 而不是begin ... end 编写匿名块?
      • 不,但您可以根据@Arsen 的回答使用括号。 :-)
      【解决方案3】:

      如果log_error 返回一个真值,你可以这样写

      foo || log_error && default
      

      如果没有:

      foo || (log_error; default)
      

      【讨论】:

      • foo || log_error; default - 将foo || log_error; 作为一个语句,将default 作为另一个语句 - 这可能不是你的意图。
      • 我没有意识到你可以将这样的 Ruby 语句组合在一起(带括号),但它完全有道理。 POLA又赢了!我想知道它与begin..end 块有何不同?
      【解决方案4】:

      为了完整起见(并且由于还没有人发布它),我将在答案中添加我最初的尝试:

      procedure(input) || proc {
        log_error
        default
      }.call
      

      我想不出任何理由在@mwp 的回答上使用它:

      procedure(input) || begin
        log_error
        default
      end
      

      因为创建 Proc 对象所涉及的额外开销(性能和可读性)。尽管一些快速的基准测试表明在大多数情况下性能差异应该可以忽略不计,因为除非procedure(input) 是假的,否则似乎不会创建 Proc 对象。

      【讨论】:

        【解决方案5】:

        考虑到所有因素,我会选择:

        foo = procedure(input)
        return foo if foo
        log_error
        default
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-24
          • 1970-01-01
          • 1970-01-01
          • 2015-07-11
          • 2014-01-27
          • 2015-10-31
          • 1970-01-01
          • 2019-03-27
          相关资源
          最近更新 更多