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