Почему '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иororiginate (как и многое из 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 ^~
этот ответ стал возможным из-за Стефан комментарии (спасибо).