Возможно ли реализовать оператора в Ruby?
a = nil
b = 1
x = a ?? b # x should == 1
x = b ?? 2 # x should == 1
Возможно ли реализовать оператора в Ruby?
a = nil
b = 1
x = a ?? b # x should == 1
x = b ?? 2 # x should == 1
Вы ищете условное назначение:
a ||= b # Assign if a isn't already set
и || Оператор
a = b || 2 # Assign if b is assigned, or assign 2
В Ruby короткозамкнутые булевы операторы (||
, &&
, and
и or
) не возвращают true
или false
, а скорее первый операнд, который определяет результат все выражение. Это работает, потому что Ruby имеет довольно простое представление об истине. Вернее, он имеет довольно простое представление об ложности: nil
является ложным и, очевидно, false
является ложным. Все остальное верно.
Итак, поскольку ||
истинно, если хотя бы один из его операндов истинен, а операнды оцениваются слева направо, это означает, что a || b
возвращает a
, когда a
является истинным. Но когда a
является ложным, тогда результат выражения зависит исключительно от b
, и поэтому возвращается b
.
Это означает, что, поскольку nil
является ложным, вы можете просто использовать ||
вместо ??
для приведенных вами примеров. (Существует также отличный a ||= b
оператор, который работает как a || a = b
, но не совсем.)
Однако это работает только потому, что вы не используете Booleans в своих примерах. Если вы ожидаете иметь дело с булевыми значениями, это не сработает:
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
на самом деле ничего).
x = b || 2
It (??
в С#) называется оператором coalesce.
Существует coalesce gem, который находится как можно ближе.
nil || 5 # => 5
false || 5 # => 5 :(
false._? 5 # => false :)