From a similar question I asked earlier, Stefan explained in a comment that or and and are actually control flow operators and should not be used as Boolean operators ( || and && respectively).
He also referred to an article explaining the reasons for these control flow statements :
and and or arise (like so many of Ruby) in Perl. In Perl, they were mainly used to change the control flow, similar to the if and unless . (...)
They give the following examples:
and
foo = 42 && foo / 2
This will be equivalent to:
foo = (42 && foo) / 2
The goal is to assign the number foo and reassign it with half its value. Thus, the and operator is useful here because of its low priority, it changes / controls , which will be a normal stream of individual expressions:
foo = 42 and foo / 2
It can also be used as the inverse of an if in a loop:
next if widget = widgets.pop
Which is equivalent:
widget = widgets.pop and next
or
useful for combining expressions together
If the first expression fails, execute the second, etc:
foo = get_foo() or raise "Could not find foo!"
It can also be used as:
Modified unless modifier:
raise "Not ready!" unless ready_to_rock?
Which is equivalent:
ready_to_rock? or raise "Not ready!"
Therefore, since sawa explained the expression a or b in:
return a or b
has a lower priority than return a , which, when executed, skips the current context and does not provide any value (void value). Then it causes an error ( repl.it execution ):
(repl): 1: void value expression
puts return a or b ^~
This answer was made possible thanks to Stefan's comments (thanks).