Can anyone put light on this expression. Seems like both are same but they are not.
a || a = b or a ||= b
and
a = a || b
if
a = 4
and b = 6
, output is always 4
This always confuse and misconcept me. Can someone please explain it?
a || a = b
looks for a
if a
is truthy, returns a
, otherwise a = b
is done i.e. you assign b
's value to a
.
a = a || b
This is an assignment operation. Here you are assigning value to a
irrespective of what value it holds. So a
equals a || b
. In second part of the statement you are looking for a
. If its value is truthy you are assigning it back to a
itself, else you are assigning b
's value to a
.
TL;DR
a = a || b
is assigning a value (depending on condition) to a
irrespective of what value it holds.
a ||= b
return a
if already present, else does a = b
Explaining with example:
You can think of a || a = b
as a || (a = b)
. Now lets assume a = 4
and b = 6
.
Since by order of precedence, this is an OR operation and since order of operations for OR is left to right we start with first a
:
# lets call this Fig. 1
a || (a = b)
^
|
.
(here)
This a
has value 4, which is a truthy value. Therefore the evaluation stops then and there and 4
is returned. ( Why? Hint: true || anything = true
)
Now lets assume a = nil
and b = 6
. We start again from same place (Fig. 1). Since a
is nil
which is falsely in Ruby, we move to the right side of the OR operation, i.e. a = b
# lets call this Fig. 2
a || (a = b)
^
|
.
(here)
As this is an assignment operation, it will get executed and we will end up assigning 6
to a
.
Coming back to a = a || b
. You can think this as a = (a || b)
. Clearly by order of precedence its an assignment operation. Since order of operations for assignment is right to left, (a || b)
is evaluated first.
# lets call this Fig. 3
a = (a || b)
^
|
.
(here)
If a = 4
and b = 6
, a || b
will return 4
(as discussed above). Else if a = nil
and b = 6
, a || b
will return 6
.
Now whatever value is returned from this ||
operation is getting assigned to the first a
.
# lets call this Fig. 4
a = (a || b)
^
|
.
(here)
A common misconception is that :
a ||= b
is equivalent to a = a || b
, but it behaves like a || a = b
In a = a || b
, a is set to something by the statement on every run, whereas with a || a = b
, a is only set if a is logically false (i.e. if it's nil or false) because || is 'short circuiting'.
Let me keep that simple :
That is, if the left hand side of the || comparison is true, there's no need to check the right hand side.
more reference RubyInside
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With