为什么在Ruby中 `return a or b` 是空值表达式错误?

20

这很好:

def foo
  a or b
end

这也是可以的:

def foo
  return a || b
end

这将返回void值表达式

def foo
  return a or b
end

为什么?它甚至没有执行;它未通过语法检查。"void value expression"是什么意思?


这不是重复的。我已经删除了所有对 || 运算符的引用,问题仍然存在。请重新打开。 - Shelvacu
@MsYvette 对不起,我应该考虑到这一点。然而,我希望它仍然可以表明,这个标记为重复的问题并没有回答我的问题。 - Shelvacu
@muistooshort 为什么你把这个标记为重复?我看了那个问题,它没有回答我的问题,但是 sawa 的回答解决了我的问题。 - Shelvacu
我认为这是另一个先例问题(事实上确实如此),但也许我太苛刻了,所以我会重新打开。 - mu is too short
3个回答

20

return a or b 被解释为 (return a) or b,因此需要计算(return a) or b的值,必须要先知道return a的值。但由于return语句不在原位置返回有效值(因为它从该位置跳出),所以设计上不能在原位置上返回有效值。因此表达式被卡在了 (some_void_value) or b,无法运行。这就是它的含义。


6
在我提出的问题“在Ruby中,`return`是否具有对某些运算符的优先级?”中,Stefan在评论中解释说,orand实际上是控制流运算符,不应作为布尔运算符(分别使用||&&)。
他还参考了“在Ruby中使用“and”和“or””:

andor(就像Ruby中的很多东西一样)源自Perl。在Perl中,它们主要用于修改控制流,类似于ifunless语句修饰符。 (...)

他们提供了以下示例:

and

foo = 42 && foo / 2

This will be equivalent to:

foo = (42 && foo) / 2 # => NoMethodError: undefined method `/' for nil:NilClass

目标是给foo赋一个数字,并重新分配它的一半值。因此,and运算符在这里非常有用,由于其低优先级,它修改/控制了个别表达式的正常流程:

foo = 42 and foo / 2 # => 21
它还可以在循环中作为反向if语句使用:
next if widget = widgets.pop

这相当于:

widget = widgets.pop and next

用于将表达式连接在一起

如果第一个表达式失败,则执行第二个表达式,以此类推:

foo = get_foo() or raise "Could not find foo!"
它也可作为以下用途之一:

reversed unless statement modifier:

raise "Not ready!" unless ready_to_rock?

这相当于:

ready_to_rock? or raise "Not ready!"
因此,正如a或b:

sawa explained

return a or b

return a 优先级低,当执行时,return a 会跳出当前上下文并且不提供任何值(空值)。这就触发了错误 (repl.it 执行):

(repl):1: void value expression

puts return a or b
              ^~

感谢Stefan的评论,使本答案得以成立。


2
由于or的优先级比||低,这意味着在执行or b之前将会执行return a,因此or b是无法访问的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接