From: "Jesús Gabriel y Galán" Date: 2008-01-24T17:25:01+09:00 Subject: Re: why must I initialize this variable? On Jan 22, 2008 11:29 PM, matt neuburg wrote: > Justin Collins wrote: > > > irb(main):001:0> puts "#{hi}" if false > > => nil > > irb(main):002:0> puts "#{hi}" if hi = "hello" > > NameError: undefined local variable or method `hi' for main:Object > > from (irb):2 > > from :0 > > Even weirder! Why does it work in the first case but not in the second. > If you're going to say that 'hi' is undefined, surely it was undefined > in line 001. Yet line 001 raised no error. > > So what's wrong with 002? It cannot be the 'puts "#{hi}"' part - you > just proved, with 001, that that part's okay. So apparently it is the > assignment part. Evidently a tailgating "if" refuses to auto-instantiate > a variable. That is what I'm attempting to get clear on. Is that a bug? > Is it expected behavior? m. Because of how the parser works. It makes a first pass, and one of the things it does is decide wheter tokens are methods or variables. The way it does that is assuming everything is a method and if it finds an assignment, from that point on, it treats it as a variable. The trick is in the "from that point on", since for the parser it's just left to right as it finds the code, it doesn't take into account evaluation order (please anyone correct me if I'm wrong). Check this: irb(main):001:0> def hi; "hi"; end => nil irb(main):002:0> puts "#{hi}" if (hi = "hello") (irb):2: warning: found = in conditional, should be == hi => nil irb(main):003:0> puts hi hello => nil As you can see, I define a method hi. The parser will treat the first hi in line 002 as a method, since it hasn't seen an assignment yet. That's why line 002 outputs "hi", because the first reference has been marked by the parser as a method call. After the hi = "hello", though, hi is treated as a variable. That's why line 003 outputs "hello". Hope this makes it a bit clearer, although I agree that this looks confusing. Jesus.