在不创建块范围的情况下运行eval

时间:2015-07-15 21:18:53

标签: ruby

我正在尝试理解Ruby中的eval和绑定上下文。

在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> 

为什么没有定义a

如果我在规避之前声明a,则将值42分配给a

在我看来,某些块范围适用于eval上下文中的局部变量可用,但声明的任何变量仅在块范围内声明。

如何在不创建新范围的情况下评估代码?

2 个答案:

答案 0 :(得分:3)

  

为什么没有定义a

a 在eval'd代码的绑定中定义,但不在其外部。这就是局部变量的工作原理。它们是它们所定义的范围的本地。这就是为什么它们被称为“本地”变量。毕竟。

  

如果我在规避之前声明a,则将值42分配给a

是的,eval的范围嵌套,就像块范围一样。

  

如何在不创建新范围的情况下评估代码?

你做不到。在Ruby 1.8和之前的版本中,eval确实会将变量泄漏到周围的范围内,但是泄漏在1.9及更高版本中已得到修复。

答案 1 :(得分:1)

这是因为a与irb不在同一个上下文中。

看看这段代码

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>'

它与块

相同
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>'

但是......

2.2.1 :001 > a=nil
 => nil 
2.2.1 :002 > eval "a = 42"
 => 42 
2.2.1 :003 > a
 => 42 

就像

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 > 

实例变量有效,因为它是&#34; self&#34;

2.2.1 :001 > eval "@b = 42"
 => 42 
2.2.1 :002 > @b
 => 42 
2.2.1 :003 > 

看看如何将上下文发送到方法。来自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"

我不知道我是否清楚,但我想说的是,真正重要的真实事情是ruby将分配/释放内存及其访问权限的上下文(或范围)。