【问题标题】:C# ?? operator in Ruby?C# ?? Ruby 中的运算符?
【发布时间】:2010-10-31 11:50:09
【问题描述】:

是否可以实施? Ruby 中的运算符?

a = nil
b = 1

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

【问题讨论】:

    标签: ruby operators null-coalescing-operator


    【解决方案1】:

    coalesce gem 离你最近的地方。

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

    【讨论】:

      【解决方案2】:
      x = b || 2
      

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

      【讨论】:

      • 由于我在回答中概述的原因,这不起作用。尝试在示例中将 b 设置为 false。
      【解决方案3】:

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

      所以,由于|| 在其至少一个 操作数为真时为真,并且操作数从左到右计算,这意味着a || b 返回a,当@ 987654333@ 是真的。但是当a为假时,表达式的结果只依赖于b,从而返回b

      这意味着,因为nil 为假,您可以只使用|| 而不是?? 作为您提供的示例。 (还有漂亮的a ||= b 运算符,类似于a || a = b,但不完全一样。)

      但是,only 有效,因为您没有在示例中使用布尔值。如果您希望处理布尔值,那将是行不通的:

      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
      

      这个可爱的 sn-p 是由多态性、开放类和 nil 实际上是一个代表虚无的对象这一事实带来的(不像,比如说,Java,null 实际上什么都没有)。

      【讨论】:

      • a ||= b 与其说是“某种”a || a = b,倒不如说是a = a || b。不是条件赋值,赋值总会发生。
      • @Theo:这就是 ISO Ruby 语言规范的当前草案所说的,但这是错误的。 MRI、YARV、JRuby、Rubinius、XRuby、MacRuby、IronRuby、Ruby.NET、MagLev、SmallRuby、tinyrb、RubyGoLightly 和所有其他 Ruby 实现,将其实现为短路条件赋值。 Ruby 编程语言(由 matz 自己共同编写)、Programming Ruby 和所有其他 Ruby 书籍都以这种方式记录了它。 RubySpec 测试套件以这种方式对其进行测试。 StackOverflow 上的几个讨论和 ruby​​-talk 上的几十个讨论都是这样说的。马茨自己也是这么说的。
      • peter cooper 文章的必填链接:rubyinside.com/…
      【解决方案4】:

      您正在寻找条件赋值:

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

      和 ||运营商

      a = b || 2 # Assign if b is assigned, or assign 2
      

      【讨论】:

      • 由于我在回答中概述的原因,这不起作用。尝试在第一个示例中将 a 设置为 false,或者在第二个示例中将 b 设置为 false。
      • 正确,@JörgWMittag。谨防真假!
      • 另外我很确定你不能用 ?? 得到一个“不能分配给 nil”的错误。但是你可以在 object 和 NilClass 上编写一个方法 ifNil 来评估一个块,就像在 smalltalk 中一样
      猜你喜欢
      • 2012-01-20
      • 1970-01-01
      • 2011-06-05
      • 2012-11-06
      • 1970-01-01
      • 2022-12-21
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      相关资源
      最近更新 更多