包含两个操作的单行 `if` return 语句

One-line `if` return statement with two actions

我正在寻找一种优雅的方式将以下 if 语句合并为一行:

if var1.nil?
  log("some message")
  return
end

我喜欢右手if 你可以说的语句

return if var1.nil?

在这种情况下,我需要执行两个操作,但以下操作不起作用:

log("some message") and return if var1.nil?

有没有办法在一行的右侧使用 if 执行两个操作(日志消息和 return)?

  1. 当你有returnbreak等方法时,你可以做(​​假设你对return值不感兴趣) :

    return log("some message") if var1.nil?
    
  2. 一个简单的通用方法是:

    (log("some message"); return) if var1.nil?
    
  3. 但是如果你不喜欢括号和分号,那么,这样做:如果and不起作用,那就意味着第一个的return值表达式是假的,这意味着 or 应该有效。

    log("some message") or return if var1.nil?
    

    一般来说,andor 之间的一个都可以,这取决于第一个表达式的计算值。

好吧,为了不依赖于布尔值评估,您总是可以这样做:

(log('some message'); return) if var.nil?

但我个人觉得它的可读性比多行版本差很多

if var1.nil?
  log('some message')
  return
end

修饰符-if 语法的一个问题是当行太长时您甚至可能不会注意到它。观察:

(log('Something really bad happened while you were doing that thing with our app and we are terribly sorry about that. We will tell our engineers to fix this. Have a good day'); return) if var.nil?

根据您的 Ruby 版本,还有另一种方法可以实现这一点(在我看来)更具可读性。在 Ruby 2.5 中引入的 yield_self 方法在 Ruby 2.6 中有一个名为 then 的别名。它适用于 Object 的所有后代(几乎所有内容,包括 nil)。

log("some message").then { return } if var1.nil?

由于 return 关键字实际上会退出当前方法或 lambda 上下文,您可以将 return 放在提供给 then 的块内。或者,您可以只 return then 的结果,因为它 return 是已解析的块值。

return log("some message").then { nil } if var1.nil?

当上下文是另一个块时,后一个示例也适用于提前退出。

some_vars.map do |var1|
  next log("some message").then { nil } if var1.nil?

  # do something with var1
end

就个人而言,我认为第一个示例读起来更好一些,但是在需要时具有一点灵活性是很好的。