2010-09-04 12 views
6

Wenn Sie debuggen, ist es sehr nützlich, dies zu tun:Wie kann ich einen Variablennamen und seinen Wert drucken, ohne den Namen zweimal einzugeben?

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

Gibt es eine Sprache, wo diese einfach zu tun? In C und C++ können Sie die stringify Makro Operator # und in Ruby verwenden fand ich diese Frage:

Ruby - print the variable name and then its value

Die Lösung, die ein Symbol verwendet: var und ein Block ist, was ich will.

In D, habe ich dies:

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

Aber ich bin nicht sicher, dass es der beste Weg, weil es nur in einfachen Fällen funktioniert. Ich habe mehrere Möglichkeiten ausprobiert, aber manchmal können Sie die Zeichenfolge abrufen, aber nicht den Wert (weil Variablen außerhalb des Gültigkeitsbereichs sind), oder Sie müssen zuerst die Vorlage mischen und dann die Funktion aufrufen.

Und was ist mit anderen Sprachen? Python? F #? Boo? Shell-Skript (welche Shell)? Perl? (Ich bleibe lieber von Perl fern, tho). Tcl? Lisp, Schema? Java? (Es ist sehr unwahrscheinlich, dass Java das kann).

Sogar in den Sprachen, in denen ich eine Lösung gefunden habe, funktioniert es nur in einfachen Fällen. Was, wenn ich einen beliebigen Ausdruck drucken möchte?

Wenn ich eine Sprache entwerfe, wäre diese Funktion ein Muss. :-)

Antwort

5

Hier ist ein sehr allgemein, aber etwas hässlich, wie es in D zu tun, Zeitfunktion Auswertung (CTFE) mit kompilieren Sie den Code als Stringliteral zu erzeugen, und eine mixin Aussage, die es zu bewerten:

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")); 
} 

Die einzigen Probleme sind, dass die Eingabe mixin überall ist ausführlich und alles, was Sie verfolgen möchten, muss in einem hässlichen String Literal sein.

Beachten Sie, dass es zwei Arten von Mixins in D. Template Mixins besser sind in vielerlei Hinsicht verhalten haben, aber String Mixins (in diesem Beispiel verwendet wird) sind etwa so allgemein wie es kommt, dass jedem Code kann im Prinzip über CTFE generiert und dann eingemischt werden.

+0

Großartig! Genau das habe ich gebraucht! Vielen Dank! Das benötigte Zitat ist subtil, oder? Schade, D erlaubt es nicht, varName zu interpolieren, damit es sauberer aussieht. Es macht mir nichts aus, den Ausdruck in eine Zeichenfolge zu setzen (ich kann q {} verwenden, um normale Token-HILIting in meinem Editor zu haben). Was Ausführlichkeit betrifft, könnte ich einen sehr kurzen Funktionsnamen verwenden :-) – marcus

2

Trivial in jedem Lisp. In Racket (née PLT Scheme):

(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

Ich halte Tcl im Grunde "Lisp ohne Datenstrukturen" (mit Streichern statt ... na ja, so ziemlich alles, wirklich), so ist es fast so einfach in Tcl wie in Lisp.

Es ist schon ein paar Jahre her, aber ich denke, so etwas wie dies den Trick tun würde:

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

set my_var 5 
log_var my_var 

Ich denke, es ist wahrscheinlich eine Art und Weise uplevel zu verwenden, um diese zu erweitern für beliebiges Ausdrücke zu arbeiten.

+0

hatte ich noch nie zuvor in Tcl programmiert (ich weiß, hat die grundlegende Syntax der Sprache), aber im Anschluss an Ihren Vorschlag kam ich mit auf den Punkt: proc log_expr {exp} { Satz x [uplevel $ 1 exp] BREAK_LINE_HERE puts "$ exp ist: $ x" } log_expr {expr 1 + 1} DAS IST FANTASTISCH !!! – marcus

Verwandte Themen