From: Brian Candler Date: 2003-04-24T16:54:58+09:00 Subject: Re: two oddities in ruby 1.8.0p2 On Thu, Apr 24, 2003 at 08:04:28AM +0900, Dave wrote: > Another oddity is one that I think has been around for a while, but I > haven't seen it discussed before (correct me if I'm wrong -- I'm new > to ruby). Oh, it has been discussed many a time :-) > It's the infamous local variable scope issue. In the > discussions I've read, methods are supposed to define a scope for > local variables. Blocks within methods also have their own scope, if > the variables have not been used already. BUT control structures like > if-else, for, while, etc. are NOT supposed to define their own scope. > How, then, to explain this example? > > i = 0 > while i < 10 > puts x if defined? x > x = 10 > i += 1 > end > > Nothing is outputted. It's nothing to do with blocks. It's because of the method/local variable ambiguity. The decision "is x a local variable or is it a method?" is made *statically*, at compile time, as the code is being read in and turned into a syntax tree. The rule is that if any statement of the form 'x = ...' has been seen earlier, then a standalone 'x' is treated as a local variable, not a method call. In your example, at the line 'puts x if defined? x', no local variable assignment to x has been seen previously. Therefore this is compiled as a method call: puts self.x if defined? self.x which always fails since you never define a method 'x' You can see it in this example: def x 33 end i = 0 while i < 10 puts x # compiled as puts self.x x = 99 puts x # compiled as puts x (the local variable) i += 1 end which prints 33 99 33 99 33 99 ... The assignment does not even have to be executed: def y 33 end y = 99 if false p y # prints 'nil' The last reference to 'y' is interpreted as a local variable because an assignment to y was seen earlier during the parsing of this method, even though at run-time it never gets executed. Some other discussions are archived here: http://www.rubygarden.org/ruby?LocalVariablesAndBlocks Cheers, Brian.