你能在Ruby中调用程序的上下文中评估代码吗?

你能在Ruby中调用程序的上下文中评估代码吗?,ruby,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)}"

基本上,我想知道是否可以用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

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

你可以用它来工作

在MRI 2.0中,您可以使用RubyVM::DebugInspector,请参见:

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
仅供参考,这里有一个“黑客方式”。 这是我对著名的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

由于ruby的set_trace_func中有一个bug,这在1.9

  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

+1看起来很有趣,我想知道这是否可以在没有块的情况下完成…我不认为在ruby 1.8.x中没有块就可以完成。我不熟悉ruby 1.9.x,所以那里的情况可能会有所不同。在ruby 2.1中,您仍然需要块,但是
Reference
的实现可以通过调用和来重做。尽管当前的实现可能允许调用本地变量之外的reader和writer方法,然而新的实现不会…这里有一个使用set_trace_func的脆弱方式的例子:应该包括免责声明:除非您实际使用它进行某种调试,否则请不要这样做。为什么@tmandry?这是一种元编程技术——它是不受欢迎的,因为所有元编程都是不受欢迎的(难以维护和调试),但它是一种新的或特殊的方式,并不危险。非常有趣!我已经把它改造成了建筑。但是
  x = 1