你可以在Ruby中调用者的上下文中评估代码吗?

基本上我想知道以下是否可以在Ruby中完成。

例如:

def bar(symbol) # magic code goes here, it outputs "a = 100" end def foo a = 100 bar(:a) end 

你必须将foo的上下文传递给bar

 def foo a = 100 bar(:a, binding) end def bar(sym, b) puts "#{sym} is #{eval(sym.to_s, b)}" end 

在1.8.X或1.9.X中没有内置的方法来获取 Ruby中的调用者绑定

您可以使用https://github.com/banister/binding_of_caller来解决。

在MRI 2.0中,您可以使用RubyVM :: DebugInspector,请参阅: https : //github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb

MRI 2.0中的工作样本:

 require 'debug_inspector' def bar(symbol) RubyVM::DebugInspector.open do |inspector| val = eval(symbol.to_s, inspector.frame_binding(2)) puts "#{symbol}: #{val}" end end def foo a = 100 bar(:a) end foo # a: 100 

这是一个更简单的语法黑客,使用传入的块绑定:

  def loginfo &block what = yield.to_s evaled = eval(what, block.binding) Rails.logger.info "#{what} = #{evaled.inspect}" end 

像这样叫:

  x = 1 loginfo{ :x } 

将退出:

  x = 1 

仅供参考,这是一种“hacky方式”。 这是我对着名的ppp.rb的(重新)实现:

 #!/usr/bin/ruby # # better ppp.rb # require 'continuation' if RUBY_VERSION >= '1.9.0' def ppp(*sym) cc = nil ok = false set_trace_func lambda {|event, file, lineno, id, binding, klass| if ok set_trace_func nil cc.call(binding) else ok = event == "return" end } return unless bb = callcc{|c| cc = c; nil } sym.map{|s| v = eval(s.to_s, bb); puts "#{s.inspect} = #{v}"; v } end a = 1 s = "hello" ppp :a, :s exit 0 

这目前在1.9中失败。[012] 由于ruby的set_trace_func中的错误。

在Ruby中检查文章输出变量绑定

 class Reference def initialize(var_name, vars) @getter = eval "lambda { #{var_name} }", vars @setter = eval "lambda { |v| #{var_name} = v }", vars end def value @getter.call end def value=(new_value) @setter.call(new_value) end end def ref(&block) Reference.new(block.call, block.binding) end def bar(ref) # magic code goes here, it outputs "a = 100" p ref.value end def foo a = 100 bar(ref{:a}) end foo