如何获取变量名称?如,
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;
答案 0 :(得分:8)
您需要执行当前变量范围的绑定,而使用the Binding class进行绑定:
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()
,并在该上下文中计算变量。
答案 1 :(得分:2)
首先,您无法实现puti
并直接调用puti a_var
以获取a_var = value of a_var
的输出。在puti
的主体,Ruby只看到puti
的形式参数名称,它无法推断出实际的参数名称。
在其他语言(如C / C ++)中,您可以使用Macro来实现puti
。那是另一个故事。
但是,您可以在Continuation的帮助下实施put :a_var
。在另一个问题“Can you eval code in the context of a caller in 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解释器将立即终止,跟踪函数无法运行。这就是最后一个“占位符”行的重点。