(no return as last line is returned implicitly, no semicolon)
EDIT: As pointed out in the comments, this is not strictly equivalent, as it will return b if a is false as well as if it’s nil (these are the only two falsy values in Ruby).
For newer python people, they see return a or b and typically think it returns a boolean if either is True. Nope. Returns a if a is truthy and then checks if b is truthy. If neither are truthy, it returns b.
Returns a if a is truthy and then checks if b is truthy. If neither are truthy, it returns b.
Not quite. If a is not truthy, then the expression a or b will always return b.
So, there is never any reason to check the truthiness of b.
you can paste this in your repl to confirm it does not.
classC:
def__repr__(self): return [k for k, v inglobals().items() if v is self][0]
def__bool__(self):
print(f"{self}.__bool__() was called")
returnFalse
a, b = C(), C()
print(f"result: {a or b}")
This doesn’t work for booleans because false is not null but also not truthy. One of things I hate about ruby is that it doesn’t have a native null coalescing operator.
Yeah, you’re quite correct, it’s not exactly equivalent, I just went on auto-pilot because it’s used so much for that purpose 🤖
It’s much closer to being a true null-coalescing operator than ‘OR’ operators in other languages though, because there’s only two values that are falsy in Ruby: nil and false. Some other languages treat 0 and "" (and no doubt other things), as falsy. So this is probably the reason Ruby has never added a true null-coalescing operator, there’s just much fewer cases where there’s a difference.
It’s going to drive me mad now I’ve seen it, though 😆 That’s usually the case with language features, though, you don’t know what you’re missing until you see it in some other language!
The || version is older and has the value of $b if $a is any false value including undef (which is pretty much Perl’s null/nil).
The // version has the value of $b iff $a is undef. Other “false” values carry through.
Ruby took both “no return required” and “no final semicolon required” from Perl (if not a few other things), I think, but it seems that // was Perl later borrowing Ruby’s || semantics. Interesting.
i.e. 0 || 1 is 1 in Perl but 0 in Ruby. Perl can 0// 1 instead if the 0, which is a defined value, needs to pass through.
Ruby:
a || b
(no
return
as last line is returned implicitly, no semicolon)EDIT: As pointed out in the comments, this is not strictly equivalent, as it will return
b
ifa
isfalse
as well as if it’snil
(these are the only two falsy values in Ruby).Python:
return a or b
i like it because it reads like a sentence so it somewhat makes sense
and you can make it more comprehensive if you want to:
return a if a is not None else b
This diverges from the OP code snippets if a has the value
False
.I personally dislike this because when you read “or” you expect some boolean result not a random object :/
there’s always the second option for you
For newer python people, they see return a or b and typically think it returns a boolean if either is True. Nope. Returns a if a is truthy and then checks if b is truthy. If neither are truthy, it returns b.
Not quite. If
a
is not truthy, then the expressiona or b
will always returnb
.So, there is never any reason to check the truthiness of
b
.you can paste this in your repl to confirm it does not.
class C: def __repr__(self): return [k for k, v in globals().items() if v is self][0] def __bool__(self): print(f"{self}.__bool__() was called") return False a, b = C(), C() print(f"result: {a or b}")
output
a.__bool__() was called result: b
Ah, good catch.
This doesn’t work for booleans because false is not null but also not truthy. One of things I hate about ruby is that it doesn’t have a native null coalescing operator.
Yeah, you’re quite correct, it’s not exactly equivalent, I just went on auto-pilot because it’s used so much for that purpose 🤖
It’s much closer to being a true null-coalescing operator than ‘OR’ operators in other languages though, because there’s only two values that are falsy in Ruby:
nil
andfalse
. Some other languages treat0
and""
(and no doubt other things), as falsy. So this is probably the reason Ruby has never added a true null-coalescing operator, there’s just much fewer cases where there’s a difference.It’s going to drive me mad now I’ve seen it, though 😆 That’s usually the case with language features, though, you don’t know what you’re missing until you see it in some other language!
Perl has both
$a || $b
and$a // $b
.The
||
version is older and has the value of$b
if$a
is any false value includingundef
(which is pretty much Perl’snull
/nil
).The
//
version has the value of$b
iff$a
isundef
. Other “false” values carry through.Ruby took both “no
return
required” and “no final semicolon required” from Perl (if not a few other things), I think, but it seems that//
was Perl later borrowing Ruby’s||
semantics. Interesting.i.e.
0 || 1
is1
in Perl but0
in Ruby. Perl can0 // 1
instead if the0
, which is a defined value, needs to pass through.