运行eval而不创建块作用域



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

考虑下面的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上下文中可用的地方,但任何声明的变量都只能在块作用域中声明。

如何在不创建新作用域的情况下eval代码?

为什么没有定义a ?

a 定义在eval代码的绑定内,而不是在它之外。这就是局部变量的工作原理。它们对于定义它们的范围来说是局部的。毕竟,这就是为什么它们被称为"局部"变量的原因。

如果在求值之前声明a,则值42赋值给a

是的,eval的作用域嵌套,就像块作用域一样。

如何在不创建新作用域的情况下eval代码?

你不能。在Ruby 1.8及更早的版本中,eval确实会将变量泄漏到周围的作用域中,但是在1.9及以后的版本中修复了这个泄漏。

这是因为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>'

和block

一样
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 > 

实例变量工作,因为它是"self"的一部分

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将分配/释放内存和他的访问。

最新更新