ruby

Variables defined in If/else statement are accessible outside of if/else?


def foo
  #bar = nil
  if true
    bar = 1
  else
    bar = 2
  end
  bar #<-- shouldn't this refer to nil since the bar from the if statement is removed from the stack?
end

puts foo # prints "1"

I always thought you had to make a temporary variable and define it as nil or an initial value so that variables defined inside an if/else statement would persist outside the scope of the if/else statement and not disappear off the stack?? Why does it print 1 and not nil?


Solution

  • Variables are local to a function, class or module defintion, a proc, a block.

    In ruby if is an expression and the branches don't have their own scope.

    Also note that whenever the parser sees a variable assignment, it will create a variable in the scope, even if that code path isn't executed:

    def test
      if true
        a = 1
      end
      puts a
    end
    
    test
    # Will print 1
    

    It's bit similar to JavaScript, though it doesn't hoist the variable to the top of the scope:

    def test
      puts a
      a = 1
    end
    
    test
    # NameError: undefined local variable or method `a' for ...
    

    So even if what you were saying were true, it still wouldn't be nil.