我想运行字符串的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
非常感谢你的表情。我很困难。
答案 0 :(得分:5)
您正在观察的行为是正常的。当您在C = 1
的调用范围内执行NameSpaces.namespace
时,NameSpaces
上会定义一个常量“C”。 (您可以尝试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
请注意,在传递给eval
的代码中可以使用Object中定义的任何常量(即全局范围),如果在评估的代码中更改了这些常量的值,则更改将是全球可见!
(即使您在BasicObject的上下文中评估代码,它不从Object继承,评估的代码也可以仍然访问在Object上定义的常量,方法是在名称前加上':: “)