Почему 'return a или b' является ошибкой выражения пустого значения в Ruby?
Это просто чудесно:
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 ответов
return a or b
трактуется как (return a) or b
, и поэтому значение return a
необходимо рассчитать значение (return a) or b
, но поскольку return
никогда не оставляет значение на месте (потому что он убегает из этой позиции), он не предназначен для возврата допустимого значения в исходной позиции. И поэтому все выражение остается с (some_void_value) or b
, и застрял. Вот что это значит.
просто так or
и низкий приоритет чем ||
что означает return a
будет выполнено до or b
, недоступен
С аналогичный вопрос я уже спрашивал, Стефан пояснил в комментарии, что or
и and
на самом деле операторы потока управления и не следует использовать как boolean операторы (||
и &&
соответственно).
он также ссылался на статья, которая объясняет причины этих операторов управления потоком:
and
иor
originate (как и многое из Ruby) в Perl. В Perl они в основном использовались для изменения потока управления, аналогичногоif
иunless
заявление модификаторов. (...)
они приводят следующие примеры:
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
полезно для сцепления выражений вместе!--37-->
если первое выражение не удается, выполните вторую, и так далее:
foo = get_foo() or raise "Could not find foo!"
его можно также использовать как:
отменено
unless
заявление модификатор:raise "Not ready!" unless ready_to_rock?
что эквивалентно:
ready_to_rock? or raise "Not ready!"
, потому как Савва объяснил the a or b
выражение в:
return a or b
ниже приоритет, чем return a
который при выполнении выходит из текущего контекста и не предоставляет никакого значения (значение void). Затем это вызывает ошибку ( repl.это исполнение):
(repl):1: выражение значения void
puts return a or b ^~
этот ответ стал возможным из-за Стефан комментарии (спасибо).