# Simple proc tracing if 0 {[Richard Suchenwirth] 2004-05-09 - One of the simplest ways to debug a [proc] is to edit in [puts] commands in interesting places. When satisfied, one should remove those, else they may do their work at unwelcome times. One simple way to avoid this is the following: proc dputs args {puts [join $args]} #proc dputs args {} ... dputs value: $value ... In your script, call ''dputs'' wherever needed. With simple removal of the # at the second definition, they will not have any effect (and be optimized out of the bytecode), and by editing a single character you can turn on or off the ''dputs'' functionality. But another idea I tried today is to "instrument" a proc's body for debugging behavior. Now, parsing a proc body for suitable instrumentation points is hard and dangerous work, considering the many possibilities. But one place in a proc body is bullet-proof to be executed in any case, namely, its very beginning. To observe how procs are called, ''[info] level ?n?'' gives us an easy tool. So the following was easily written:} proc +trace proc { proc $proc [info args $proc] \ "puts \[info level]:\[info level 0]\n#:\n[info body $proc]" } if 0 {Every time a proc is called, which has been instrumented by ''+trace'', it reports the whole call line, including its names and arguments. This modification happens only in memory (not in the source file), so when next starting the app, the trace is gone. This simple mechanism makes experimenting, expecially with recursion, even easier than it was. To remove a +trace from a proc body is easy too, and harmless when it is accidentally called on a not-instrumented proc, if you just choose a marker comment (#: here) that doesn't appear elsewhere in your code: } proc -trace proc { regsub .+#:\n [info body $proc] "" body proc $proc [info args $proc] $body } # Testing: proc gcd {u v} {expr {$u? [gcd [expr $v%$u] $u]: $v}} +trace gcd puts with:[gcd 360 123] -trace gcd puts without:[gcd 360 123] if 0 {produces first the traced call history, and then nothing but the result: 1:gcd 360 123 2:gcd 123 360 3:gcd 114 123 4:gcd 9 114 5:gcd 6 9 6:gcd 3 6 7:gcd 0 3 with:3 without:3 Documented feature (=bug :): the code above works only for procs without default arguments. If you want these too, replace the calls to ''info args'' in +trace and -trace with just ''args'', and add this one:} proc args proc { set res {} foreach a [info args $proc] { if [info default $proc $a def] {lappend a $def} lappend res $a } set res } #-- Testing again: proc foo {a {b 1}} {expr $a+$b} puts args:[args foo] if 0 { args:a {b 1} ---- See also [trace] for the lew ''trace execution'' features ---- [Arts and crafts of Tcl-Tk programming] }