45

有没有可能实现??Ruby 中的运算符?

a = nil
b = 1

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

4 回答 4

55

在 Ruby 中,短路布尔运算符(||、、&&和)不返回或and,而是返回确定整个表达式结果的第一个操作数。这行得通,因为 Ruby 有一个相当简单的真理概念。或者更确切地说,它有一个相当简单的虚假概念:是虚假的,显然是虚假的。其他一切都是真的。ortruefalsenilfalse

因此,因为||当它的至少一个操作数为真时为真,并且操作数从左到右求值,这意味着当为真时a || b返回。但是当为假时,则表达式的结果完全取决于,因此被返回。aaabb

这意味着,因为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

于 2009-06-04T22:08:32.863 回答
36

您正在寻找条件分配:

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

和 || 操作员

a = b || 2 # Assign if b is assigned, or assign 2
于 2009-06-04T21:34:36.877 回答
3
x = b || 2

它(??在 C# 中)称为合并运算符。

于 2009-06-04T21:36:10.807 回答
1

有一个聚结宝石,它离你很近。

nil || 5 # => 5
false || 5 # => 5 :(
false._? 5 # => false :)
于 2014-01-12T00:58:46.640 回答