Получить имя локальной переменной - PullRequest
8 голосов
/ 14 июля 2010

При разработке и отладке я иногда хотел бы написать 1-строчную строку, которая выводит имена, типы и значения группы переменных. Проблема в том, что я не знаю, как получить доступ к имени переменной, если вообще могу.

Вот первая попытка:

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 ]

13 голосов
/ 14 июля 2010
foo = 1
bar = "42"
baz = Hash.new

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

Но это, конечно, не поможет, если вам нужен метод с 1 аргументом.

4 голосов
/ 15 июля 2010

Вот небольшой отладочный код, который я использую повсеместно (я помещаю его в отдельный файл, чтобы его можно было использовать везде, где это необходимо).Это можно использовать двумя способами.Передав одно или несколько значений, он просто проверяет их и записывает результат в $ 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 драгоценный камень.

3 голосов
/ 14 июля 2010

Нет, потому что 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

Чтобы получить имя конкретной переменной экземпляра, просматривайте все переменные экземпляра, пока не найдете его сзначение, соответствующее вашей переменной экземпляра.

2 голосов
/ 15 июля 2010
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

Или вы можете просто использовать отладчик. В конце концов, для этого они и были изобретены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...