Why is `return a or b` a void value expression error in Ruby?

落花浮王杯 提交于 2020-01-06 07:11:29

问题


This is just fine:

def foo
  a or b
end

This is also fine:

def foo
  return a || b
end

This returns void value expression:

def foo
  return a or b
end

Why? It doesn't even get executed; it fails the syntax check. What does void value expression mean?


回答1:


return a or b is interpreted as (return a) or b, and so the value of return a is necessary to calculate the value of (return a) or b, but since return never leaves a value in place (because it escapes from that position), it is not designed to return a valid value in the original position. And hence the whole expression is left with (some_void_value) or b, and is stuck. That is what it means.




回答2:


In "Does `return` have precedence to certain operators in Ruby?" which I asked, Stefan explained in a comment that the or and and are actually control flow operators and should not be used as boolean operators (|| and && respectively).

He also referenced "Using “and” and “or” in Ruby":

and and or originate (like so much of Ruby) in Perl. In Perl, they were largely used to modify control flow, similar to the if and unless statement modifiers. (...)

They provide the following examples:

and

foo = 42 && foo / 2

This will be equivalent to:

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

The goal is to assign a number to foo and reassign it with half of its value. Thus the and operator is useful here due to its low precedence, it modifies/controls what would be the normal flow of the individual expressions:

foo = 42 and foo / 2 # => 21

It can also be used as a reverse if statement in a loop:

next if widget = widgets.pop

Which is equivalent to:

widget = widgets.pop and next

or

useful for chaining expressions together

If the first expression fails, execute the second one and so on:

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

It can also be used as a:

reversed unless statement modifier:

raise "Not ready!" unless ready_to_rock?

Which is equivalent to:

ready_to_rock? or raise "Not ready!"

Therefore as sawa explained the a or b expression in:

return a or b

Has lower precedence than return a which, when executed, escapes the current context and does not provide any value (void value). This then triggers the error (repl.it execution):

(repl):1: void value expression

puts return a or b
              ^~

This answer was made possible due to Stefan comments.




回答3:


Simply because or has lower precedence than || which means return a will be executed before or b, or b is therefore unreachable



来源:https://stackoverflow.com/questions/49800242/does-return-have-precedence-to-certain-operators-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!