Reputation: 2623
I'm trying to evaluate the expression (a=10) || (rr=20)
while the rr variable is not defined
so typing rr
in the ruby console before evaluating the previous expression returns
rr
NameError: undefined local variable or method `rr' for main:Object
from (irb):1
from :0
When I write the expression (a=10) || (rr=20)
it returns 10, and when I write rr afterwards it says nil
(a=10) || (rr=20)
rr # => nil
so, why is this happening? Shouldn't rr be defined only if the second argument of the || operator is evaluated, which should be never based on the documentation?
Upvotes: 10
Views: 3115
Reputation: 13719
This happens because the ruby interpreter defines a variable when it sees an assignment to it (but before it executes the actual line of code). You can read more about it in this answer.
Boolean OR (||
) expression will evaluate to the value of left hand expression if it is not nil
and not false
, else ||
will evaluate to the value of right hand expression.
In your example the ruby interpreter sees an assignment to a
and rr
(but it doesn't execute this line yet), and initializes (defines, creates) a
and rr
with nil
. Then it executes the ||
expression. In this ||
expression, a
is assigned to 10
and 10
is returned. r=20
is not evaluated, and rr
is not changed (it is still nil
). This is why in the next line rr
is nil
.
Upvotes: 12
Reputation: 5914
As @DOC said, &&
and ||
are known as short circuited
conditional operators.
In case of ||, if the left part of || expression returns true, the right part won't be executed.
That means the right part will be executed only if the left part of ||
expression returns false.
In case of &&, right part of the
&&expression will be executed only if left part of && returns true.
In the given scenario (a=10) || (rr=20)
, rr=20 won't be executed since the ruby expression a=10
returns true
. Note that in ruby assignment expression returns true except nil and false
.
Upvotes: 5
Reputation: 211580
When the parser discovers a variable it is automatically valid within the context it's defined in. Evaluating rr
on its own is not valid. Evaluating rr=20
is sufficient to cause a definition even if the value assignment never occurs.
This is a quirk of how Ruby tries to discern between variables and method calls. It's imperfect but usually works out for the best.
Upvotes: 2
Reputation: 26979
I think variable definement happens at the parsing stage, not the execution moment. So when it evaluates the line, it parses the whole thing and the variable is defined, but unassigned.
Upvotes: 3