2010-07-14 16 views
8

Quando si sviluppa il debug di &, a volte vorrei poter scrivere un 1-liner che ha scaricato i nomi, tipi di valori & di un gruppo di variabili. Il problema è che non so come accedere al nome di una variabile, se posso.Ottieni il nome di una variabile locale

Ecco un primo tentativo:

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

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

mi piacerebbe l'uscita di questo programma di essere qualcosa di simile:

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

Non so che cosa ??? dovrebbe essere al di sopra. Può essere fatto?

+0

Potresti invertire la tua logica e andare con la soluzione di Glenn: http://stackoverflow.com/questions/58482/ruby-get-a-variables-name La mia comprensione è che non è possibile ottenere il nome di una variabile. – Pat

+0

@Pat: questo è in effetti lo stesso della soluzione di Leventix, ma con una sintassi diversa. Quindi immagino che la risposta sia sì. :) –

+0

Non sono sicuro che exemplor possa gestire più variabili, ma exemplor ti permette di chiamare 'Mostra (variabile)' ti dà il nome della variabile e il suo valore. http://github.com/quackingduck/exemplor –

risposta

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

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

Ma questo, ovviamente, non aiuta se si desidera un metodo con 1 argomento.

+0

Brillante! Grazie! Vorrei poter sopravvivere questo due volte. –

+2

Ho appena trovato una soluzione molto interessante per questo: http://thinkrelevance.com/blog/2009/09/23/quick-and-easy-logging-with-logbuddy.html – Leventix

3

No, perché foo/bar/baz non sono variabili di istanza nel codice. Sono variabili locali (le variabili di istanza iniziano con @). C'è un modo per farlo con le variabili di istanza e il metodo Object#instance_variables, però:

@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 

per ottenere il nome di una particolare variabile di istanza, ciclo attraverso tutte le variabili di istanza fino a trovare uno con un valore che corrisponde la tua variabile di istanza.

4

Ecco un po 'di codice di debug che uso ovunque (lo inserisco in un file separato in modo che possa essere richiesto ovunque sia necessario). Può essere utilizzato in due modi. Passato uno o più valori, li controlla semplicemente e scrive il risultato su $ stderr. Ma passato un blocco che restituisce una o più cose, le scrive con i loro nomi.

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

Nota: La funzione q, e di più, è ora disponibile nella cute_print gemma.

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 

Oppure, è possibile utilizzare solo un debugger. Questo è quello per cui sono stati inventati, dopo tutto.

Problemi correlati