Get The Name Of A Local Variable

前端 未结 4 698
逝去的感伤
逝去的感伤 2020-12-30 11:43

When developing & debugging, I sometimes wish I could write a 1-liner that dumped the names, types & values of a bunch of variables. The problem is I don\'t know ho

相关标签:
4条回答
  • 2020-12-30 11:57
    foo = 1
    bar = "42"
    baz = Hash.new
    
    %w(foo bar baz).each do |vn|
        v = eval(vn)
        puts "#{vn} = (#{v.class}) #{v}"
    end
    

    But this, of course, doesn't help you if you want a method with 1 argument.

    0 讨论(0)
  • 2020-12-30 12:09

    Here's a little bit of debug code I use all over the place (I stick it in a separate file so that it can be required wherever needed). It can be used two ways. Passed one or more values, it simply inspects them and writes the result to $stderr. But passed a block which returns one or more things, it writes them out with their names.

    #!/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
    

    Note: The q function, and more, is now available in the cute_print gem.

    0 讨论(0)
  • 2020-12-30 12:11
    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
    

    Or, you could just use a debugger. That's what they were invented for, after all.

    0 讨论(0)
  • 2020-12-30 12:19

    No, because foo/bar/baz are not instance variables in your code. They are local variables (instance variables start with a @). There is a way to do it with instance variables and the Object#instance_variables method, though:

    @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
    

    To get the name of a particular instance variable, loop through all of the instance variables until you find one with a value that matches your instance variable.

    0 讨论(0)
提交回复
热议问题