Ruby Scoping Bug?

class Foo
  def title
    "Oh hai."
  end

  def buggy
    puts title

    if false
      title = 'Oh noes!'
    end

    puts title
  end
end

Foo.new.buggy

This code outputs:

Oh hai.
nil

Isn’t it odd that the variable being created in an if-false block is still being created and set to nil? Hopefully this is fixed in Ruby 1.9.

10 Comments

  1. Oleg Andreev says:

    This is a feature, not a bug. Ruby knows when “a” is a method or a local variable only by lexer heuristics. When lexer encounters local variable assignment (a=, a||=) within the scope (e.g. method body; if-then-else blocks are not new scopes by design), it marks “a” as a local variable and you have no way to call a method “a” then.

    Sometimes this funny behavior is useful:
    http://oleganza.tumblr.com/post/57906287/ruby-local-variable-semantics

    In my practice i have never had a trouble with these semantics: i have small methods, thus little number of local variables, and well-chosen names for everything.

  2. Wow, interesting bug! I don’t have an explanation for it either, and was able to reproduce it in both Ruby 1.8.6 and 1.8.7. It’s good to know this issue exists, as I’m sure it could cause some debugging headaches… However, I generally try to avoid naming my local variables the same as my methods, because of the potential for confusion.

  3. Oleg is right, but it may seem surprising.

    See here for some more somewhat surprising results: http://pennysmalls.com/2007/10/01/why-ruby-is-not-my-favourite-programming-language/

  4. ste says:

    class Foo
    def title
    “Oh hai.”
    end

    def buggy
    puts title

    if false
    title = ‘Oh noes!’
    end

    puts title()
    end
    end

    Foo.new.buggy

    Oh hai.
    Oh hai.

    Like Oleg said, “if” does not introduce a new scope: at first “title” is resolved to a method invocation, then intepreter sees a variable assignment inside the _current_ scope, so from there on “title” is bound to a local variable. If for some reason you want to have both a variable and a method with the same name in your code, the least you can do is not fooling the interpreter :-)
    I think this “bug” is a very small price to pay to have uniform access.

  5. cies breijs says:

    anybody tested it with 1.9?

    i think this is one of the issues Matz pointed out he wants to get ‘rite’ in 1.9/2.0.

    _cies.

  6. Radarek says:

    Guys, everything is expected. If interpreter would decide that given name is local variable or method in runtime it could works even strangely. Consider this example:

    http://pastie.org/375282

    class Foo
    def title
    “Oh hai.”
    end

    def buggy
    puts title

    if rand(2) == 0
    title = ‘Oh noes!’
    end

    puts title
    end
    end

    Foo.new.buggy

    Depending on returned value by rand(2) it would use sometimes variable title and sometimes call a method. It would be very evil. Now you can be sure: it always use local variable (even if it will be set to nil).

    Another advantage of that behavior is that you IDE/editor can say during editing that given name is variable or method. Netbeans do that by make bold methods so looking at code you can see it clearly. It’s very important because one of frequent allegations that people saying is that it’s difficult to say looking on source code if something is method or variable, for example:

    def foo
    # many lines of code
    x = a + b # a and b could be variable of method
    end

    But we can for 100% say if something is method or variable. As far as I know Perl can’t do that (sometimes) and decide it on runtime. We should be thankful for that.

  7. Radarek says:

    “When lexer encounters local variable assignment (a=, a||=) within the scope (e.g. method body; if-then-else blocks are not new scopes by design), it marks “a” as a local variable and you have no way to call a method “a” then.”

    It’s not true. You can always use “()” to make explicit method call.

  8. I have been considering buying a corrugated metal warehouse for a second home. We have phoned a a few different businesses and we have been given quotes from 4 . We undeniably like one that stands out. I am wanting a big shot on this site has some understanding with buying a metal store. Here is the riding arena I prefer:

    http://www.rhinobldg.com/steel-building-gallery/bigimages/pic5.jpg

    I am hoping for skilled answers from the subscribers here from anybody who has purchased or erected a corrugated metal framed pole barn already. What questions should be advantageous to look for. What makes one steel storage building better than another. We are enormously interested in building a metal horse areanas for the second home. Click the link to see the firm I like top.

    Some and every assistance is treasured.

  9. Cesar Glise says:

    beneficial good this submit deserves nothing hahaha just joking :P nice post :P

  10. Patrizier 4 says:

    thanks, for this nice article. I found it through google and i found it very helpful. i will look for more interesting articles at this blog. (=

Leave a Reply