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

时间:2016-01-21 22:02:40

标签: ruby return operator-precedence or-operator

这很好:

def foo
  a or b
end

这也没关系:

def foo
  return a || b
end

这会返回void value expression

def foo
  return a or b
end

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

3 个答案:

答案 0 :(得分:12)

return a or b被解释为(return a) or b,因此return a的值是计算(return a) or b的值所必需的,但由于return永远不会离开值到位(因为它从该位置逃逸),它不是设计为在原始位置返回有效值。因此整个表达式都留有(some_void_value) or b,并且被卡住了。这就是它的意思。

答案 1 :(得分:3)

我之前提到的similar questionStefan在评论中解释说orand实际上是控制流操作符,应该不能用作布尔运算符(分别为||&&)。

他还引用了article that explains the reasoning behind these control flow operators

  在Perl中,

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

他们提供以下示例:

and

foo = 42 && foo / 2
     

这相当于:

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

or

  

用于将表达式链接在一起

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

foo = get_foo() or raise "Could not find foo!"

它也可以用作:

  

反向unless语句修饰符:

raise "Not ready!" unless ready_to_rock?

相当于:

ready_to_rock? or raise "Not ready!"

因此sawa explained a or b表达式为:{/ p>

return a or b

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

  

(repl):1:无效值表达

puts return a or b
              ^~

由于Stefan comments(谢谢),这个答案成为可能。

答案 2 :(得分:2)

只是因为orlower precedence而非||,这意味着return a将在or b之前执行,因此or b无法访问