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
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
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
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).
a ||= b
isn't so much "kind of" a || a = b
, but exactly a = a || b
. It is not conditional assignment, the assignment will always happen. –
Snotty 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
x = b || 2
It (??
in C#) is called the coalesce operator.
There is the coalesce gem, which is as close as you'll get.
nil || 5 # => 5
false || 5 # => 5 :(
false._? 5 # => false :)
Ruby has a null coalescing operator &.
, called the "Safe Navigation Operator":
irb(main):004:0> a = nil
=> nil
irb(main):005:0> a&.foo
=> nil
irb(main):006:0> a = Struct.new(:foo).new(foo: 3)
=> #<struct foo=3>
irb(main):007:0> a&.foo
=> 3
It's not exactly what you're asking for, but this question ranks so high on google for "ruby null coalescing operator" that it's worth mentioning here.
&.
is not a null coalescing operator but the safe navigation operator; it does something else entirely. Thus, your answer is entirely unrelated to the question. –
Doubleripper © 2022 - 2024 — McMap. All rights reserved.