为什么`在Ruby中返回a或b`是一个void值表达式错误?

She*_*acu 17 ruby return operator-precedence or-operator

这很好:

def foo
  a or b
end
Run Code Online (Sandbox Code Playgroud)

这也没关系:

def foo
  return a || b
end
Run Code Online (Sandbox Code Playgroud)

返回void value expression:

def foo
  return a or b
end
Run Code Online (Sandbox Code Playgroud)

为什么?它甚至没有被执行; 它没有通过语法检查.什么void value expression意思?

saw*_*awa 16

return a or b被解释为(return a) or b,因此值return a是计算值的必要值(return a) or b,但由于return从未留下值(因为它从该位置逃逸),因此它不能在原始位置返回有效值.因此,整个表达留下(some_void_value) or b,并被卡住.这就是它的含义.


CPH*_*hon 6

在“ `return` 是否优先于 Ruby 中的某些运算符? ”我问过,Stefan在评论中解释说orand实际上是控制流运算符,不应用作布尔运算符(||&&)。

他还引用了“在 Ruby 中使用“and”和“or ”:

and并且or起源于 Perl(就像很多 Ruby 一样)。在 Perl 中,它们主要用于修改控制流,类似于ifunless语句修饰符。(……)

他们提供了以下示例:

and

foo = 42 && foo / 2
Run Code Online (Sandbox Code Playgroud)

这将等同于:

foo = (42 && foo) / 2 # => NoMethodError: undefined method `/' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)

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

foo = 42 and foo / 2 # => 21
Run Code Online (Sandbox Code Playgroud)

它也可以用作if循环中的反向语句:

next if widget = widgets.pop
Run Code Online (Sandbox Code Playgroud)

这相当于:

widget = widgets.pop and next
Run Code Online (Sandbox Code Playgroud)

or

用于将表达式链接在一起

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

foo = get_foo() or raise "Could not find foo!"
Run Code Online (Sandbox Code Playgroud)

它也可以用作:

反向unless语句修饰符:

raise "Not ready!" unless ready_to_rock?
Run Code Online (Sandbox Code Playgroud)

这相当于:

ready_to_rock? or raise "Not ready!"
Run Code Online (Sandbox Code Playgroud)

因此,正如sawaa解释a or b那样:

return a or b
Run Code Online (Sandbox Code Playgroud)

具有较低的优先级return a,当执行时,转义当前上下文并且不提供任何值 ( void value )。然后触发错误(repl.it execution):

(repl):1: 空值表达式

puts return a or b
              ^~
Run Code Online (Sandbox Code Playgroud)

由于Stefan评论,这个答案成为可能。