a ||= b
is often perceived as a = a || b
but it’s more like a || a = b
In the misconception, a is always set after ruby decides a or b is logically true.
But ||=
reads more if the left hand side of the ||
comparison is true, there’s no need to check the right hand side.
Don’t confuse +=
or -=
or [op]= with anything related to ||=
or &&=
. They’re entirely different ideas and are implemented entirely differently.
Some examples you can run in irb
:
a = nil
b = 20
a ||= b # a || a = b
=> 20 #since a is nil, it uses b
# More complicated example:
h = {}
def h.[]=(k, v)
puts "Setting hash key #{k} with #{v.inspect}"
super
end
# 1. The standard ||= approach
h[:x] ||= 10 #h[:x] is initially nil so now it is set as 10
h[:x] ||= 20 #h[:x] is now 10 so it still renders 10
# 2. The a = a || b approach
h[:y] = h[:y] || 10 #h[:y] is now set to 10
h[:y] = h[:y] || 20 #h[:y] decides between 10 || 20, both are true so it uses the left value and reassigns h[:y] with the same value
# 3. The a || a = b approach
h[:z] || h[:z] = 10 #same as ||=
h[:z] || h[:z] = 20 #same as ||=
# Output
# => Setting hash key x with 10
# => Setting hash key y with 10
# => Setting hash key y with 10
# => Setting hash key z with 10