获取局部变量的名称

时间:2010-07-14 19:35:41

标签: ruby

开发时&调试,我有时希望我能写一个倾斜名称,类型和类型的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) ...

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

4 个答案:

答案 0 :(得分:13)

foo = 1
bar = "42"
baz = Hash.new

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

但是,如果你想要一个带有1个参数的方法,这当然没有用。

答案 1 :(得分:4)

以下是我在整个地方使用的一些调试代码(我将其粘贴在一个单独的文件中,以便在需要的地方可以使用它)。它可以用两种方式。传递一个或多个值,它只是检查它们并将结果写入$ 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
q i       # => 1
q {:i}    # => i = 1

name = "Fred"
q [name, name.length]         # => ["Fred", 4]
q {[:name, 'name.length']}    # => name = "Fred", name.length = 4

注意:现在cute_print gem中提供了q功能等功能。

答案 2 :(得分:3)

不,因为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

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

答案 3 :(得分:2)

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

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