Wtf?

Posted by tobi — 09:17 PM Apr 10


if false
  var = nil
end

p var.nil? #=> true ??? 

Comments

  • Dr Nic 10 Apr 21:46

    I guess its a scope issue; you created local var variable inside the if statement.

    For example:

    var = "booya" 
    if false
      var = nil
    end
    
    var.nil? # => false
    
  • tobi 10 Apr 21:52

    Well ok but why is the variable in existence?

    
    def var
      'OH HI!'
    end
    
    if false
      var = nil
    end
    
    p var.nil? #=> true 
    
  • Dr Nic 10 Apr 22:00

    Ooh nice one.

    def var
      'OH HI!'
    end
    
    if false
      puts "I'm in false" 
      var = nil
    end
    
    var().nil? # => false
    var.nil?   # => true
    
  • Ezra 10 Apr 22:24

    It’s a ruby quirk to allow local variables and method calls without parens to co-exist. At parse time if ruby sees any assignments that look like a local variable it creates a local var initialized to nil. That’s why if false; foo = ‘hi’; end will create a ‘foo’ local variable but set it to nil since the inside of the if false is never executed.

  • Pete Forde 10 Apr 22:42

    This one almost had me, but setting var = nil was just a red herring.

    if false
      var = "jP rules!" 
    end
    var.nil? # => true
  • Nathan Youngman 10 Apr 22:46

    Trippy. I imagine you may have already come across Monday’s “Ruby’s not ready” article. The conclusions are a bit off (not ready for what?) but there is a fair amount of truth to Ruby’s quirkiness, as your wtf post further confirms. http://glyphobet.net/blog/essay/228

  • Dave Hoover 11 Apr 00:10

    Ruby has variable scoping… http://redsquirrel.com/cgi-bin/dave/dynamic/variable.scoping.html

  • Phil 11 Apr 02:21

    Another explanation: http://blog.caboo.se/articles/2006/03/08/your-ruby-gotcha-of-the-day

  • ste 11 Apr 03:38

    I thought that every Ruby programmer knew about this trick :-) Javascript doesn’t have it, so you are forced to pre-assign every variable which only gets assigned inside a block that might not be executed (as in your example). I see this as a clear application of the PolS: you are using “var” in your code, so why should you check if it is defined or not? By the way, this behavior is clearly documented in the Pickaxe book (p. 314 on the beta 3d edition).

  • Dr Nic 11 Apr 07:06

    @ezra – sweet, thx for the explanation.

  • Emmanuel Oga 11 Apr 12:53

    Why do people consider this a quirk? I use this behavior very often….

    def do_something(param)
      if param == :a
        result = 1
      elsif param == :b
        result = 2
      end
    
      complex_thing_that_i_dont_want_to_dup(result, "x", "y", "z") if result
    end
    

    Consider the alternatives:

    def do_something(param)
      if param == :a || param == :b
        if param == :a
          result = 1
        else
          result = 2
        end
    
        complex_thing_that_i_dont_want_to_dup(result, "x", "y", "z")
      end
    end
    

    or even [uglier?]

    def do_something(param)
      if param == :a
        complex_thing_that_i_dont_want_to_dup(1, "x", "y", "z")
      elsif param == :b
        complex_thing_that_i_dont_want_to_dup(2, "x", "y", "z")
      end
    end
    

    I rather the first form, using the ruby “quirk”.

  • tobias Lütke 11 Apr 18:06

    Emmanuel: that’s not really what i meant. The problem is that ruby insert’s an invisible var = nil into the method above it. If you have a method called var for example it will be overshadowed after you assign var = something in the blog. Even if the var = something is never executed.

Commenting are now closed…