【问题标题】:Maintaining local variables between eval of code在代码的 eval 之间维护局部变量
【发布时间】:2014-11-07 23:49:51
【问题描述】:

考虑以下 Ruby 代码:

class Foo
  def bar; 42; end
  def run(code1,code2)
    binding.eval(code1,'c1')
    binding.eval(code2,'c2')
  end
end

Foo.new.run "x=bar ; p x", "p x"

目的是动态评估某些代码(创建局部变量),然后运行可以访问这些变量的其他代码。结果是:

c2:1:in `run': undefined local variable or method `x' for #<Foo:…> (NameError)

请注意,上述方法仅在 eval 改变绑定时有效,它仅在修改现有局部变量时才有效,而不是创建新变量。我不一定需要(或希望)每次运行都改变外部绑定,我只需要能够访问先前的绑定以进行后续代码评估。

如何评估两个代码块并维护它们之间的局部变量?


出于好奇,这个的实际应用是custom tool,它可以执行一个脚本文件,然后放入一个 REPL。我希望 REPL 能够访问脚本文件创建的所有局部变量。

【问题讨论】:

    标签: ruby eval metaprogramming


    【解决方案1】:

    您需要存储Binding 并重复使用相同的。如果你反复调用binding——即使是在同一个范围内——你会得到一个新的绑定。因此,对于演示功能,我们可以这样做:

    class Foo
      def initialize; @b = binding; end
      def bar; 42; end
      def run(code)
        @b.eval( code, '(yourcode)' )
      end
    end
    
    f = Foo.new
    f.run "x=bar ; p x"  #=> 42
    f.run "p x"          #=> 42
    

    【讨论】:

    • 方法体中的 (@binding ||= binding).eval(code, '(yourcode)') 对我有用 - 只是简单一点。
    • @August 有趣!这很有帮助。所以每次调用binding都会创建一个新的绑定;只要我创建一个 Binding 并存储它,就没有理由返回该绑定。谢谢!
    • @August 我已编辑我的答案以纳入您的反馈。如果您想发布自己的答案,我很乐意恢复我的更改并支持(并可能接受)您的答案。
    • 您可以将其保留在您的答案中 :)
    猜你喜欢
    • 2014-01-25
    • 2015-08-05
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    • 2015-10-21
    • 1970-01-01
    相关资源
    最近更新 更多