views:

169

answers:

3

When you are debugging, it's very useful to do this:

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

Is there any language where this is easy to do? In C and C++ you can use the stringify macro operator # and in Ruby I found this question:

http://stackoverflow.com/questions/2603617/ruby-print-the-variable-name-and-then-its-value

The solution that uses a symbol :var and a block is what I want.

In D, I used this:

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

But I'm not sure it's the best way, because it works only in simple cases. I have tried several ways, but sometimes you can get the string, but not the value (because variables are out of scope), or you have to mixin the template first and then call the function.

And what about other languages? Python? F#? Boo? Shell script (whichever shell)? Perl? (I prefer to stay away from Perl, tho). Tcl? Lisp, Scheme? Java? (it's highly unlikely that Java can do this).

Even in the languages where I found some kind of solution, it only works for simple cases. What if I want to print an arbitrary expression?

If I were designing a language, this feature would be a must-have. :-)

+2  A: 

Trivial in any 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"
mquander
A: 

I consider Tcl basically "Lisp without any data structures" (with strings instead of ... well, pretty much anything, really), so it's almost as easy in Tcl as in Lisp.

It's been a couple years, but I think something like this would do the trick:

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

set my_var 5
log_var my_var

I think there's probably a way to use uplevel to extend this to work for arbitrary expressions.

Ken
I had never programmed in Tcl before (I did know the basic syntax of the language), but following your suggestion I came up with this:proc log_expr {exp} {set x [uplevel 1 $exp] BREAK_LINE_HEREputs "$exp is: $x"}log_expr {expr 1+1}THIS IS AWESOME!!!!
marcus
+5  A: 

Here's a very general, but slightly ugly way to do it in D, using compile time function evaluation (CTFE) to generate the code as a string literal, and a mixin statement to evaluate it:

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

The only problems are that manually typing mixin everywhere is verbose and whatever you want to trace needs to be inside an ugly string literal.

Note that there are two kinds of mixins in D. Template mixins are better behaved in many ways, but string mixins (used in this example) are about as general as it gets, in that any code can in principle be generated via CTFE and then mixed in.

dsimcha
Great! That's exactly what i needed! Thanks! The quoting needed is subtle, isn't it? Too bad D doesn't allow to interpolate varName to make it look cleaner.I don't mind putting the expression inside a string (i can use q{} to have normal token hiliting in my editor). As for verbosity, i could use a very short function name :-)
marcus