From: Brian Candler Date: 2011-01-26T18:37:02+09:00 Subject: Re: The finer points of postfix conditionals. Peter Vandenabeele wrote in post #977488: > To understand this better, I used the method 'defined?'. > Would 'defined?' be a correct way to determine if a name was > already 'initialized as a local variable' in this case? > > $ rvm use 1.9.2 # (same behavior in 1.8.7) > Using /home/peterv/.rvm/gems/ruby-1.9.2-p136 > $ irb > 001:0> defined?(x) #=> nil > 002:0> if false > 003:1> x = 10 > 004:1> end #=> nil > 005:0> defined?(x) #=> "local-variable" > 006:0> x #=> nil Yes, but you should rarely if ever need this in practice. Ruby is in general a highly dynamic language, but one thing which is static is the decision as to whether a bare name is a local variable or a method call. This is done at *parse* time, before code is even executed (whereas definition of classes and methods are done at run time, by executing the code containing 'class' and 'def' statements) Hence even if you dynamically create a local variable using 'eval', a subsequent non-eval reference to that variable won't pick it up. Run the following as a .rb script (not in irb): def x "yay" end eval "x=1" puts x # yay puts defined?(x) # method puts eval("x") # 1 You can see that x was chosen to be a method call, because no assignment to x was seen previously (the eval isn't executed until runtime). This is even clearer if you use something like ParseTree to show the parsed code. You can, however, force a bare name to be a method call instead of a local variable - again, decided at parse time: def x "yay" end x = 1 puts x # 1 puts x() # yay puts self.x # private method 'x' called puts y # undefined local variable or method 'y' puts y() # undefined method 'y' I think the reasons for this approach are: 1. Language design - you don't need to declare variables, and you don't need to use () after every method call 2. Decidability - you can tell just by scanning source code whether 'x' is a local variable or a method call. (You only need to scan from the previous 'def' or 'class' statement, since these start a new scope) 3. Efficiency - you don't want to have to search at run time to determine whether 'x' is a local variable or a method call at that point in the code every time it executes -- Posted via http://www.ruby-forum.com/.