How can I print a variable name and its value without typing the name twice?
When you are debugging, it's very use开发者_如何学Pythonful 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. :-)
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.
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"
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.
精彩评论