2010-09-04 15 views
6

Quando si esegue il debug, è molto utile per fare questo:Come posso stampare un nome di variabile e il suo valore senza digitare il nome due volte?

var = calc() 
print("var:", var) 

C'è qualche lingua in cui questo è facile da fare? In C e C++ è possibile utilizzare la stringa i macro operatore # e in Ruby ho trovato questa domanda:

Ruby - print the variable name and then its value

La soluzione che utilizza un simbolo: var e un blocco è quello che voglio.

In D, ho usato questo:

void trace(alias msg)() { 
    writeln(msg.stringof ~ ":" ~ to!string(msg)); 
} 

ma non sono sicuro che sia il modo migliore, perché funziona solo in casi semplici. Ho provato diversi modi, ma a volte è possibile ottenere la stringa, ma non il valore (perché le variabili non sono comprese), oppure è necessario prima mescolare il modello e quindi chiamare la funzione.

E le altre lingue? Pitone? F #? Boo? Script di shell (qualsiasi shell)? Perl? (Preferisco stare lontano da Perl, tho). Tcl? Lisp, Scheme? Giava? (è altamente improbabile che Java possa farlo).

Anche nelle lingue in cui ho trovato qualche tipo di soluzione, funziona solo per casi semplici. Cosa succede se voglio stampare un'espressione arbitraria?

Se stavo progettando una lingua, questa funzione sarebbe un must. :-)

risposta

5

Ecco un modo molto generale, ma un po 'brutto per farlo in D, con la compilazione di valutazione funzione time (CTFE) per generare il codice come una stringa letterale, e una dichiarazione mixin per valutarla:

import std.stdio, std.math; 

// CTFE function that generates trace code. 
string trace(string varName) { 
    return "writeln(\"" ~ varName ~ ": \", " ~ varName ~ ");"; 
} 

void main() { 
    // Trace a function call. 
    mixin(trace("sqrt(5)")); 

    // Trace a variable. 
    int foo = 5; 
    mixin(trace("foo")); 
} 

Gli unici problemi sono che digitando manualmente mixin ovunque sia prolisso e qualunque cosa si desideri tracciare deve essere all'interno di una brutta stringa letterale.

Nota che ci sono due tipi di mixins in mixins D. modello sono meglio comportati in molti modi, ma mixins stringa (utilizzati in questo esempio) sono quanto di più generale, come si arriva, in quel codice qualsiasi può in linea di principio essere generato tramite CTFE e poi mixato in.

+0

Grande! Questo è esattamente ciò di cui avevo bisogno! Grazie! La citazione necessaria è sottile, non è vero? Peccato che D non permetta di interpolare varName per renderlo più pulito. Non mi interessa inserire l'espressione all'interno di una stringa (posso usare q {} per avere un token normale nel mio editor). Per quanto riguarda la verbosità, potrei usare un nome di funzione molto breve :-) – marcus

2

Trivial in qualsiasi Lisp. In Racket (PLT Scheme nata):

(define-syntax-rule (debug-info expr) 
    (format "~a is ~a" (quote expr) expr)) 

(let ((long-boring-name 5)) 
    (display (debug-info long-boring-name))) 

# displays "long-boring-name is 5" 

(let ((fifty-two 52)) 
    (display (debug-info (+ fifty-two 6)))) 

# displays "(+ fifty-two 6) is 58" 
0

considero Tcl fondamentalmente "Lisp senza strutture di dati" (con le stringhe al posto di ... beh, praticamente nulla, in realtà), quindi è quasi facile in Tcl come in Lisp.

E 'stato un paio di anni, ma penso che qualcosa di simile sarebbe fare il trucco:

proc log_var {var} { 
    upvar 1 $var x 
    puts "$var is: $x" 
} 

set my_var 5 
log_var my_var 

Penso che probabilmente c'è un modo per utilizzare uplevel di estendere questo a lavorare per espressioni arbitrarie.

+0

non avevo mai programmato in Tcl prima (ho fatto conoscere la sintassi di base della lingua), ma in seguito il suo suggerimento sono arrivato fino a questo: proc log_expr {exp} { set x [uplevel 1 $ exp] BREAK_LINE_HERE mette "$ exp è: $ x" } log_expr {expr 1 + 1} QUESTO È FANTASTICO !!!! – marcus

Problemi correlati