Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I print a variable name and its value without typing the name twice?

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:

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. :-)

like image 423
marcus Avatar asked Sep 04 '10 00:09

marcus


2 Answers

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.

like image 151
dsimcha Avatar answered Oct 04 '22 22:10

dsimcha


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"
like image 25
mqp Avatar answered Oct 04 '22 22:10

mqp