C# ?? operator in Ruby?

前端 未结 4 1372
猫巷女王i
猫巷女王i 2020-12-16 09:05

Is it possible to implement the ?? operator in Ruby?

a = nil
b = 1

x = a ?? b # x should == 1
x = b ?? 2 # x should == 1
相关标签:
4条回答
  • 2020-12-16 09:40
    x = b || 2
    

    It (?? in C#) is called the coalesce operator.

    0 讨论(0)
  • 2020-12-16 09:41

    You're looking for conditional assignment:

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

    and the || operator

    a = b || 2 # Assign if b is assigned, or assign 2
    
    0 讨论(0)
  • 2020-12-16 09:41

    There is the coalesce gem, which is as close as you'll get.

    nil || 5 # => 5
    false || 5 # => 5 :(
    false._? 5 # => false :)
    
    0 讨论(0)
  • 2020-12-16 09:43

    In Ruby, the short-circuiting Boolean operators (||, &&, and and or) do not return true or false, but rather the first operand that determines the outcome of the entire expression. This works, because Ruby has a rather simple idea of truth. Or rather, it has a rather simple idea of falsehood: nil is false, and obviously false is false. Everything else is true.

    So, since || is true when at least one of its operands is true, and operands are evaluated from left to right, this means that a || b returns a, when a is true. But when a is false, then the outcome of the expression is solely dependent on b, and thus b is returned.

    That means that, because nil is false, you can just use || instead of ?? for the examples that you gave. (There is also the nifty a ||= b operator, which kind of works like a || a = b, but not quite.)

    However, that only works, because you don't use Booleans in your examples. If you expect to deal with Boolean values, that won't work:

    b = false
    
    x = b || 2 # x should be == false, but will be 2
    

    In that case, you will have to use #nil?, and a conditional expression:

    b = false
    
    x = unless b.nil? then b else 2 end # x should be == 2
    

    or using the ternary conditional operator:

    b = false
    
    x = b.nil? ? 2 : b # x should be == false
    

    If you want to, you can wrap that up in a nice method:

    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
    

    This cute snippet brought to you by polymorphism, open classes and the fact that nil is actually an object representing nothingness (unlike, say, Java, where null is actually nothing).

    0 讨论(0)
提交回复
热议问题