Variable hoisting in Ruby
A few days ago, I found a strange thing to look at the code of my colleagues. The code that caused the error was working well. Through a few experiments and searches, I came to know a new fact that I did not know about Ruby.
Bit of Weirdness
puts x
When we run this code, we will get an error obviously.
NameError: undefined local variable or method `x' for main:Object
Next, try this:
if true
x = 1
end
puts x
Output 1 as expected. Now, let’s try:
if false
x = 1
end
puts x
What are the results? An error? Or nil? Or maybe 1? Unlike the expectation that an error will occur, you can see that nil
is printed. What’s going on?
Hoisting
The “magic” here is done by Ruby’s parser. when the parser runs over the if-clause it ‘hoists’ each variable to the top of its scope, declaring and setting it to nil
, regardless of whether it will actually be executed. After that the interpreter figure out if the x = 1 line will ever get executed.
Summary
The local variable is created when the parser encounters the assignment, not when the assignment occurs:
a = 0 if false # does not assign to ap local_variables # prints [:a, :_]p a # prints nil