获取局部变量的名称

在进行开发和调试时,我有时希望能写出一个用于转储一堆变量的名称,类型和值的1-liner。 问题是我不知道如何访问变量的名称,如果我可以的话。

这是第一次尝试:

foo = 1 bar = "42" baz = Hash.new [foo, bar, baz].each do |v| puts "#{v.???} = (#{v.class}) #{v}" end 

我希望这个程序的输出是这样的:

 foo = (Fixnum) 1 bar = (String) 42 baz = (Hash) ... 

我不知道是什么??? 应该在上面。 可以这样做吗?

 foo = 1 bar = "42" baz = Hash.new %w(foo bar baz).each do |vn| v = eval(vn) puts "#{vn} = (#{v.class}) #{v}" end 

但是,如果你想要一个带有1个参数的方法,这当然不会对你有帮助。

这是我在各地使用的一些调试代码(我将它粘贴在一个单独的文件中,以便在需要的地方可以使用它)。 它可以用两种方式。 传递一个或多个值,它只是检查它们并将结果写入$ stderr。 但是传递了一个返回一个或多个东西的块,它用它们的名字写出来。

 #!/usr/bin/ruby1.8 def q(*stuff, &block) if block s = Array(block[]).collect do |expression| value = eval(expression.to_s, block.binding).inspect "#{expression} = #{value}" end.join(', ') $stderr.puts s else stuff.each do |thing| $stderr.print(thing.inspect + "\n") end end end i = 1 qi # => 1 q {:i} # => i = 1 name = "Fred" q [name, name.length] # => ["Fred", 4] q {[:name, 'name.length']} # => name = "Fred", name.length = 4 

注意: q函数等等现在可以在cute_print gem中使用。

不,因为foo / bar / baz不是代码中的实例变量。 它们是局部变量(实例变量以@开头)。 但是有一种方法可以使用实例变量和Object#instance_variables方法来实现:

 @foo = 1 @bar = 2 @baz = 3 instance_variables.each do |var| value = instance_variable_get var puts "#{var} = (#{value.class}) #{value}" end # outputs: # @foo = (Fixnum) 1 # @bar = (Fixnum) 2 # @baz = (Fixnum) 3 

要获取特定实例变量的名称,请遍历所有实例变量,直到找到具有与实例变量匹配的值的变量。

 foo = 1 bar = "42" baz = Hash.new Varspec = Struct.new(:name, :type, :value, :inspect_str) do def to_s "#{name} = (#{type}) #{inspect_str}" end end lvars = local_variables.map {|lvar| lvar = lvar.to_s val = eval(lvar) val = val.dup rescue val Varspec.new(lvar, val.class, val, val.inspect) } puts lvars # baz = (Hash) {} # bar = (String) "42" # foo = (Fixnum) 1 

或者,您可以使用调试器。 毕竟,这就是他们发明的东西。