class Foo
def self.run(n,code)
foo = self.new(n)
@env = foo.instance_eval{ binding }
@env.eval(code)
end
def initialize(n)
@n = n
end
end
Foo.run( 42, "p @n, defined? foo" )
#=> 42
#=> "local-variable"
上面的示例程序旨在评估Foo
实例范围内的任意代码。它这样做,但绑定被code
方法中的局部变量“污染”。我不希望foo
,n
或code
对eval'd代码可见。所需的输出是:
#=> 42
#=> nil
如何创建(a)在对象实例范围内的绑定,但(b)没有任何局部变量?
我创建绑定而不是仅仅使用instance_eval(code)
的原因是real usage我需要keep the binding around for later usage,以保留在其中创建的局部变量。
答案 0 :(得分:4)
这样吗?还是我错过了一些重要的事情?
class Foo
attr_reader :b
def initialize(n)
@n = n
@b = binding
end
def self.run(n, code)
foo = self.new(n)
foo.b.eval(code)
end
end
Foo.run(42, "p @n, defined?(foo)")
# 42
# nil
或进一步向下移动以获得更少的上下文
class Foo
def initialize(n)
@n = n
end
def b
@b ||= binding
end
def self.run(n, code)
foo = self.new(n)
foo.b.eval(code)
end
end
Foo.run(42, "p @n, defined?(foo), defined?(n)")
# 42
# nil
# nil
答案 1 :(得分:2)
<强>答案强>:
module BlankBinding
def self.for(object)
@object = object
create
end
def self.create
@object.instance_eval{ binding }
end
end
<强>描述强>:
为了获得没有局部变量的绑定,您必须在没有任何局部变量的范围内调用binding
。调用方法会重置局部变量,因此我们需要这样做。但是,如果我们这样做:
def blank_binding_for(obj)
obj.instance_eval{ binding }
end
...生成的绑定将具有obj
局部变量。你可以这样隐藏这个事实:
def blank_binding_for(_)
_.instance_eval{ binding }.tap{ |b| b.eval("_=nil") }
end
...但这只会删除局部变量的值。 (目前Ruby中没有remove_local_variable
方法。)如果要在IRB或ripl之类的地方使用绑定,在每次评估后设置_
变量,这就足够了。 ,因此会掠过你的影子。
但是,如顶部的答案所示,还有另一种方法可以将值传递给方法,而这是通过实例变量(或类变量或全局变量)传递的。由于我们使用instance_eval
将self
转换为我们的对象,因此我们为调用该方法而创建的任何实例变量都不会在绑定中可用。