Why can I refer to a variable outside of an if/unless/case statement that never ran?

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 variable x (with value nil) henceforth in the current scope. Since if/unless/case/for/while do not create a new scope, x is defined and available outside the code block. And since the inner block is never evaluated as the conditional is false, x is not assigned to (and is thus nil).

Here’s a similar example:

defined?(x) and x = 0
x  #=> nil

Note that this is a rather high-level overview of what happens, and isn’t necessarily exactly how the parser works.

Leave a Comment