'||=' operator in Ruby
Could some one explain to me the meaning of the following Ruby code? (I saw this code snippet in one guy's project):
car ||= (method_1 || method_2 || method_3 || method_4)
What is the difference between the above code and the following code?
car = method_1 || method_2 || method_3 || method_4
----------update--------------
Ok, I got the meaning of ||=
operator after read @Dave's explanation, my next question is if both method_2
, method_3
and method_4
return a value, which one's value will be assigned to car
? (I suppose car
is nil initially)
It's an assignment operator for 'Conditional Assignment'
See here -> http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators
Conditional assignment:
x = find_something() #=>nil
x ||= "default" #=>"default" : value of x will be replaced with "default", but only if x is nil or false
x ||= "other" #=>"default" : value of x is not replaced if it already is other than nil or false
Operator ||= is a shorthand form of the expression:
x = x || "default"
EDIT:
After seeing OP's edit, the example is just an extension of this, meaning:
car = method_1 || method_2 || method_3 || method_4
Will assign the first non-nil or non-false return value of method_1, method_2, method_3, method_4 (in that order) to car
or it'll retain its old value.
car ||= (method_1 || method_2)
is equivalent to
car = (car || (method_1 || method_2))
In general,
x op= y
means
x = x op y
the ||=
operator checks first, if your value car
is already set. If car
returns nil, it will assign the first value on the right side which doesn't return nil
or false
.
So, given your example from above, if you assign a value to car like
car = "BMW"
and you execute you code-snippet, the value of car will still be "BMW";
If method_1 returns (for instance) the String "Value from Method 1"
and car is nil
or false
, then car this String will be assigned to car
car = nil
car ||= (method_1 || method_2)
car # => "Value from Method 1"
If method_1 also returns nil
/false
, it will check for the value in method_2, and so forth, until it gets some sort of true-value
The difference to your second code-snippet is, that in case of ||=
the variable car
will be evaluated first, and set if it returns nil or false.
If you use =
only, no evaluation will happen and car will be set to the first value on the right that doesn't return nil or false.
-- UPDATE --
To answer your update question, the value on the right side will be evaluated from left to right, so the first one that doesn't return nil
or false
will be assigned.
car = nil
# method_1 => "nil"
# method_2 => "false"
# method_3 => "value method 3"
# method_4 => "I won't be called"
car ||= (method_1 || method_2 || method_3 || method_4)
# => "value method 3"
car ||= (method_1 || method_2 || method_3 || method_4)
car will retain its value after this statement is run, if car initially is not nil.
If car was nil before this statement, the first non nil value to return from method_1, method_2, ... will be assigned to car.
car = method_1 || method_2 || method_3 || method_4
In this case, car will be re-assigned the first non nil value to return out of the methods even if car already has a non nil value before this statement ran