It does not really retrieve it - it is just telling Ruby to interpret ``a''
as
an initialized local variable.
There is different way to see it
Without the `eval part' you would
get a NameError, this difference is really surprising (to me at
least;-).
pigeon% ruby
def aa(x)
a = 1
end
^D
pigeon%
It is at least interesting that running the free form (no method) of the
same Ruby snippet
---
if x
eval "p a" # no premonition
end
a = 1
---
also raises a NameError.
it raise a NameError for `x'
pigeon% cat b.rb
#!/usr/bin/ruby
if x
eval "p a"
end
a = 1
pigeon%
pigeon% b.rb
./b.rb:2: undefined local variable or method `x' for #<Object:0x401c6ce0> (NameError)
pigeon%
Now this work
pigeon% cat b.rb
#!/usr/bin/ruby
def x
p "ruby has called me"
true
end
if x
eval "p a"
end
a = 1
pigeon%
pigeon% b.rb
"ruby has called me"
nil
pigeon%
so basically it uses the `insight' (that `b' is a local variable and not
dynamic
variable ) gained at the end of the method body and to reinterpret the
previous lines in that new light?
No : ruby first compile the def, find the local variable `b' and store
the name of this variable in a node of this def. When it has found the
line `eval "p a"' it was interpreted as `eval("p a")' and ruby has created
a node to call the method #eval
When ruby call the def, it retrieve the node where are stored the name of
the local variables and create a local variable `b'. When #eval is called,
it compile the string, at this time ruby know that it exist a local
variable `b' and it interpret "b = 1" like an access to this local
variable.
Without the line "b = 2", the local variable is not created when the
method is called and eval "b = 1" will also be interpreted as an access to
a *new* local variable
Guy Decoux