din*_*022 3 ruby binding scope constants
我想运行字符串的eval来定义局部变量和常量.我想在不同的命名空间中执行此操作.我可以使用局部变量但不使用常量.有没有办法修改下面的NameSpaces模块,以便一个绑定/命名空间中定义的常量不被另一个看到?
# Example run under ruby 1.9.1
module NameSpaces
def self.namespace(namespace)
return binding
end
end
b1 = NameSpaces.namespace("b1")
b2 = NameSpaces.namespace("b2")
# Set a 'x', then check to make sure its still set in the scope of 'b1'
puts b1.eval("x = 1") # => 1
puts b1.eval("x") # => 1
# Check to make sure 'x' is NOT set in the scope of 'b2'
begin
puts b2.eval("x") # NameError exception expected here
rescue Exception => e
puts e.to_s # => undefined local variable or method `x'
# for NameSpaces:Module (THIS IS AS EXPECTED.)
end
# Set constant 'C' and do the same checks
puts b1.eval("C = 1") # => 1
puts b1.eval("C") # => 1
# Check to make sure 'C' is NOT set in the scope of 'b2'
begin
puts b2.eval("C") # (I DON'T GET AN EXCEPTION. NOT AS I HAD HOPED FOR.)
rescue Exception => e
puts e.to_s
end
Run Code Online (Sandbox Code Playgroud)
非常感谢你的外观.我很困惑.
您正在观察的行为是正常的.当您C = 1在调用范围内执行时,NameSpaces.namespace定义了常量"C" NameSpaces.(您可以通过尝试确认NameSpaces::C.)
要获得所需的效果,您需要使用匿名模块的绑定.试试这个:
namespace1 = Module.new.class_eval("binding")
namespace2 = Module.new.class_eval("binding")
namespace1.eval("C = 1")
namespace1.eval("C")
=> 1
namespace2.eval("C")
NameError: uninitialized constant #<Module:0xf09180>::C
Run Code Online (Sandbox Code Playgroud)
请注意,在Object中定义的任何常量(即全局范围)将在传递给的代码中可用eval,并且如果在评估的代码中更改了此类常量的值,则更改将全局可见!
(即使您在不从Object继承的BasicObject的上下文中评估代码,评估的代码仍然可以通过在名称前加上'::' 来访问在Object上定义的常量)
| 归档时间: |
|
| 查看次数: |
394 次 |
| 最近记录: |