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?

+3


source to share


2 answers


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 assigned a

.



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.

+3


source


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.

+1


source







All Articles