Executing eval without creating block scope
I am trying to understand the eval and binding contexts in Ruby.
Please note the following: irb
irb(main):001:0> eval "a = 42"
=> 42
irb(main):002:0> a
NameError: undefined local variable or method `a' for main:Object
from (irb):2
from /Users/niels/.rbenv/versions/2.1.3/bin/irb:11:in `<main>'
irb(main):003:0>
Why a
not defined?
If I declare a
prior to rejection, the value 42 is assigned a
.
It seems to me that some kind of block scope applies where local variables are available inside the eval context, but any declared variables are only declared in block scope.
How do I do eval code without creating a new scope?
source to share
Why
a
not defined?
a
is defined in the binding of the eval'd code, but not outside of it. This is how local variables work. They are local to the area in which they are defined. This is why they are still called "local" variables.
If I declare
a
prior to rejection, the value 42 is assigneda
.
Yes, the eval
areas are just like the block area.
How do I do eval code without creating a new scope?
You can not. Ruby 1.8 and earlier would eval
indeed move variables into the surrounding scope, but this leak was recorded in 1.9 and beyond.
source to share
This is because a is not in the same context as irb.
Look at this code
2.2.1 :001 > eval "a = 42"
=> 42
2.2.1 :002 > a
NameError: undefined local variable or method `a' for main:Object
from (irb):2
from /home/hbranciforte/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
this is the same as blocks
2.2.1 :001 > 1.times{|a| b=1}
=> 1
2.2.1 :002 > b
NameError: undefined local variable or method `b' for main:Object
from (irb):2
from /home/hbranciforte/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
But...
2.2.1 :001 > a=nil
=> nil
2.2.1 :002 > eval "a = 42"
=> 42
2.2.1 :003 > a
=> 42
he like
2.2.1 :001 > b=nil
=> nil
2.2.1 :002 > 1.times{|a| b=1}
=> 1
2.2.1 :003 > b
=> 1
2.2.1 :004 >
Instance variables work because they are part of the self
2.2.1 :001 > eval "@b = 42"
=> 42
2.2.1 :002 > @b
=> 42
2.2.1 :003 >
See how the context can be sent to the method. from http://ruby-doc.org/core-2.2.0/Binding.html
def get_binding(param)
return binding
end
b = get_binding("hello")
b.eval("param") #=> "hello"
I don't know if I was clear, but I want to say that the real thing that really matters is the context (or area) where ruby ββwill allocate / deallocate memory and access to it.
source to share