В Ruby булевы операторы короткого замыкания (||
, &&
, and
и or
) не возвращают true
или false
, а скорее первый операнд, определяющий результат все выражение. Это работает, потому что у Ruby довольно простое представление об истине. Вернее, у него довольно простое представление о лжи: nil
ложно и, очевидно, false
ложно. Все остальное верно.
Таким образом, поскольку ||
имеет значение true, когда хотя бы один из его операндов имеет значение true, а операнды вычисляются слева направо, это означает, что a || b
возвращает a
, когда a
правда. Но когда a
ложно, тогда результат выражения зависит исключительно от b
, и поэтому возвращается b
.
Это означает, что, поскольку nil
является ложным, вы можете просто использовать ||
вместо ??
для приведенных вами примеров. (Существует также отличный оператор a ||= b
, который работает как a || a = b
, но не совсем.)
Однако, только работает, потому что вы не используете логические значения в своих примерах. Если вы собираетесь работать с логическими значениями, это не сработает:
b = false
x = b || 2 # x should be == false, but will be 2
В этом случае вам придется использовать #nil?
и условное выражение:
b = false
x = unless b.nil? then b else 2 end # x should be == 2
или используя троичный условный оператор:
b = false
x = b.nil? ? 2 : b # x should be == false
Если хотите, можете обернуть это хорошим методом:
class Object
def _? b = nil
return self
end
end
class NilClass
def _? b = nil
return yield if block_given?
return b
end
end
b = false
x = b._? { 2 } # x should be == false
x = b._? 2 # x should be == false
Этот симпатичный фрагмент, принесенный вам полиморфизмом, открытыми классами и тем фактом, что nil
на самом деле является объектом , представляющим ничто (в отличие, скажем, от Java, где null
равно на самом деле ничего).