我正在尝试理解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将分配/释放内存和他的访问。