(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.Typescript/Javascript too
Not strictly equivalent, since
||
tests for truthiness, not just null.That’s fair, but it’s close enough that it functions identically
Only for the
null
case. For other cases it doesn’t function identically, since it also treats""
,0
andundefined
the same asnull
.