C # ?? оператор в рубине? - PullRequest
       40

C # ?? оператор в рубине?

36 голосов
/ 05 июня 2009

Возможно ли реализовать ?? оператор в Ruby?

a = nil
b = 1

x = a ?? b # x should == 1
x = b ?? 2 # x should == 1

Ответы [ 4 ]

48 голосов
/ 05 июня 2009

В 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 равно на самом деле ничего).

35 голосов
/ 05 июня 2009

Вы ищете условное назначение:

a ||= b  # Assign if a isn't already set

и || оператор

a = b || 2 # Assign if b is assigned, or assign 2
5 голосов
/ 05 июня 2009
x = b || 2

Он (?? в C #) называется оператором объединения.

1 голос
/ 12 января 2014

Есть драгоценный камень coalesce , который так близко, как вы получите.

nil || 5 # => 5
false || 5 # => 5 :(
false._? 5 # => false :)
...