When a is undefined, then a || 1 will throw an error, but a = a || 1 will not. Isn’t that a little bit inconsistent?
irb(main):001:0> a
NameError: undefined local variable or method 'a' for main:Object
from (irb):1
from c:/ruby/bin/irb:12:in '<main>'
irb(main):002:0> a || 1
NameError: undefined local variable or method 'a' for main:Object
from (irb):2
from c:/ruby/bin/irb:12:in '<main>'
irb(main):003:0> a = a || 1
=> 1
Here, you are evaluating
a, which isn’t defined. Therefore, you get an exception.Here, you still have to evaluate
ato determine the value of the boolean expression. Just like above,aisn’t defined. Therefore, you get an exception.Here,
ais defined. It is defined to be an uninitialized local variable. In Ruby, uninitialized variables evaluate tonil, so the right hand side of the assignment expression evaluates tonil || 1which evaluates to1, so the return value of the assignment expression is1and the side effect is thatais initialized to1.EDIT: It seems that there is some confusion on when variables get defined and when they get initialized in Ruby. The get defined at parse time but initialized at runtime. You can see it here:
foois undefined.At this point,
foois defined, even though the line will never get executed. The fact that the line never gets executed is completely irrelevant, because the interpreter has nothing to do with this anyway: local variables are defined by the parser, and the parser obviously sees this line.There is no error, because
foois defined, and it evaluates tonilbecause it is uninitialized.