Ruby:获取变量名称
我如何获得变量名称? 例如,
def get_var_name(var) # return variable name end myname = nil get_var_name myname #=> myname
初衷:
somevar = "value" puti somevar #=> somevar = "value" # that is a shortage for # `puts "somevar = #{somevar.inspect}"`
我的尝试:
def puti(symb) var_name = symb.to_s var_value = eval(var_name) puts "#{var_name} = #{var_value.inspect}" end puti :@somevar # that actually will work only with class vars or whatever considering var scope;
首先,你puti
并直接调用puti a_var
来获得输出a_var = value of a_var
。 在puti
的主体,Ruby只看到puti
的forms参数名称,它无法推断出实际的参数名称。
在其他语言如C / C ++中,您可以使用Macro来实现您的puti
。 那是另一个故事。
但是,您可以在Continuation的帮助下实现put :a_var
。 在另一个问题“ 你可以在Ruby中调用者的上下文中评估代码吗? ”, Sony Santos提供了一个caller_binding实现来获得调用者的绑定(类似于perl调用函数)。
实现应该稍微改变一下,因为callcc
在第一次返回时返回块的返回值。 因此,您将获得Continuation
的实例而不是nil
。 这是更新版本:
require 'continuation' if RUBY_VERSION >= '1.9.0' def caller_binding cc = nil # must be present to work within lambda count = 0 # counter of returns set_trace_func lambda { |event, file, lineno, id, binding, klass| # First return gets to the caller of this method # (which already know its own binding). # Second return gets to the caller of the caller. # That's we want! if count == 2 set_trace_func nil # Will return the binding to the callcc below. cc.call binding elsif event == "return" count += 1 end } # First time it'll set the cc and return nil to the caller. # So it's important to the caller to return again # if it gets nil, then we get the second return. # Second time it'll return the binding. return callcc { |cont| cc = cont; nil } end # Example of use: def puti *vars return unless bnd = caller_binding vars.each do |s| value = eval s.to_s, bnd puts "#{s} = #{value.inspect}" end end a = 1 b = 2 puti :a, :b e = 1 # place holder... # => a = 1 # b = 2
请注意, puti
不应该是程序的最后一个语句,否则ruby解释器将立即终止并且跟踪function无法运行。 所以这就是最后一个“占位符”线的重点。
您需要执行当前变量范围的绑定 ,这与Binding类一起使用 :
def puti(symb, the_binding) var_name = symb.to_s var_value = eval(var_name, the_binding) puts "#{var_name} = #{var_value.inspect}" end somevar = 3 puti :somevar, binding # Call the binding() method #=> outputs "somevar = 3"
binding()
方法给出一个Binding对象,它记住调用方法时的上下文。 然后将绑定传递给eval()
,并在该上下文中计算变量。