NameError: undefined - have parsing rules for local variables changed in Ruby 2.1.2?

后端 未结 3 2012
执笔经年
执笔经年 2021-01-18 07:31

I am getting NameError: undefined local variable or method with ruby 2.1.2

As observed in this question, expressions like:

bar if bar =          


        
3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-18 07:59

    There is no difference with regards to whether bar is defined or not. In both cases, bar is undefined in the body. However, in the latter case, the body is never evaluated, therefore it doesn't matter. You never resolve the name bar, therefore you never get an error during name resolution.

    Local variables are defined when an assignment is parsed. They are initialized when an assignment is executed.

    It's perfectly fine for a variable to be unitialized. It will just evaluate to nil in that case:

    if false
      bar = 42
    end
    
    bar
    # => nil
    

    However, if the variable is undefined, then Ruby doesn't know whether a bare word is a local variable or a receiverless argumentless message send:

    foo
    # NameError: undefined local variable or method `foo'
    #                                     ^^^^^^^^^
    # Ruby doesn't know whether it's a variable or a message send
    

    Compare with:

    foo()
    # NoMethodError: undefined method `foo'
    # ^^^^^^^^^^^^^
    
    self.foo
    # NoMethodError: undefined method `foo'
    # ^^^^^^^^^^^^^
    

    All together now:

    foo()
    # NoMethodError: undefined method `foo'
    
    self.foo
    # NoMethodError: undefined method `foo'
    
    foo
    # NameError: undefined local variable or method `foo'
    
    if false
      foo = 42
    end
    
    foo
    # => nil
    
    foo = :fortytwo
    
    foo
    # => :fortytwo
    

    The trouble in this particular case is that the order in which the expressions are parsed (and thus the order in which variables are defined) does not match with the order in which the expressions are executed.

    The assignment is executed first, which would make you assume that bar would be defined in the body. But it isn't, because the body was parsed first and thus an I don't know whether this is a method or a variable node was inserted into the syntax tree before the assignment was ever seen.

    However, if that node is never interpreted, i.e. the condition is false, then nothing bad will happen.

提交回复
热议问题