Why does the following code not throw an error?
if false
x = 0
end
x #=> nil
Whereas the following does throw an error:
y # NameError: undefined local variable or method `y' for main:Object
The same thing happens with unless & case statements.
It’s because of how the Ruby parser works. Variables are defined by the parser, which walks through the code line-by-line, regardless of whether it will actually be executed.
Once the parser sees
x =, it defines the local variablex(with valuenil) henceforth in the current scope. Sinceif/unless/case/for/whiledo not create a new scope,xis defined and available outside the code block. And since the inner block is never evaluated as the conditional is false,xis not assigned to (and is thusnil).Here’s a similar example:
Note that this is a rather high-level overview of what happens, and isn’t necessarily exactly how the parser works.