【问题标题】:Get The Name Of A Local Variable获取局部变量的名称
【发布时间】:2010-07-14 19:35:41
【问题描述】:

在开发和调试时,我有时希望我可以编写一个 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) ...

我不知道上面的??? 应该是什么。这个可以吗?

【问题讨论】:

标签: ruby


【解决方案1】:
foo = 1
bar = "42"
baz = Hash.new

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

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

【讨论】:

【解决方案2】:

这里有一些我在各处使用的调试代码(我将它放在一个单独的文件中,以便在需要的地方需要它)。它可以有两种使用方式。传递一个或多个值,它只是检查它们并将结果写入 $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

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

【讨论】:

    【解决方案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
    

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

    【讨论】:

      【解决方案4】:
      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
      

      或者,您可以只使用调试器。毕竟,它们就是为此而发明的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-12
        • 2012-07-02
        • 1970-01-01
        • 1970-01-01
        • 2017-08-14
        • 1970-01-01
        相关资源
        最近更新 更多