你能在Ruby中调用程序的上下文中评估代码吗?
基本上,我想知道是否可以用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)}"
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