调试时,执行此操作非常有用:
var = calc()
print("var:", var)
有没有哪种语言容易做到?在C和C ++中,您可以使用stringify宏运算符#,在Ruby中我发现了这个问题:
Ruby - print the variable name and then its value
使用符号的解决方案:var和block就是我想要的。
在D中,我使用了这个:
void trace(alias msg)() {
writeln(msg.stringof ~ ":" ~ to!string(msg));
}
但我不确定这是最好的方法,因为它只适用于简单的情况。我尝试了几种方法,但有时你可以得到字符串,但不是值(因为变量超出范围),或者你必须首先混合模板然后调用函数。
那么其他语言呢?蟒蛇? F#?嘘? Shell脚本(无论哪个shell)? Perl的? (我更喜欢远离Perl,tho)。 TCL? Lisp,Scheme? Java的? (Java不太可能这样做)。
即使在我找到某种解决方案的语言中,它也适用于简单的情况。如果我想打印任意表达式怎么办?
如果我正在设计一种语言,这个功能将是必备的。 : - )
答案 0 :(得分:5)
这是在D中执行它的一种非常通用但稍微丑陋的方式,使用编译时函数评估(CTFE)生成代码作为字符串文字,并使用mixin
语句来评估它:
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"));
}
唯一的问题是在任何地方手动输入mixin
都是冗长的,无论你想跟踪什么都需要在一个丑陋的字符串文字中。
请注意,D中有两种mixins。模板mixin在很多方面都表现得更好,但字符串mixins(在本例中使用)大致与它一样, any 代码原则上可以通过CTFE生成,然后混合进来。
答案 1 :(得分:2)
任何Lisp都是微不足道的。在Racket(néePLT计划)中:
(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"
答案 2 :(得分:0)
我认为Tcl基本上是“没有任何数据结构的Lisp”(用字符串代替......好吧,几乎任何东西,真的),所以它在Tcl和Lisp一样容易。
已经过了几年,但我觉得这样的事情可以解决问题:
proc log_var {var} {
upvar 1 $var x
puts "$var is: $x"
}
set my_var 5
log_var my_var
我认为可能有一种方法可以使用uplevel
来扩展它以适用于任意表达式。