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?
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.
From a similar question I previously 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 an article that explains the reasoning behind these control flow operators:
andandororiginate (like so much of Ruby) in Perl. In Perl, they were largely used to modify control flow, similar to theifandunlessstatement modifiers. (...)
They provide the following examples:
and
foo = 42 && foo / 2This 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
unlessstatement 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 (thank you).
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/34935179/why-is-return-a-or-b-a-void-value-expression-error-in-ruby