'''`[info] [level]`''' indicates the current [level], and can also describe the command for the current level. ** See Also ** [https://core.tcl-lang.org/tcl/tktview?name=8b9854c3d8%|%info level 0 returns incompatible result in exported command since Tcl 8.6.9], {2019 01 15}: A description how `[info level]` behaves inconsistently in various circumstances, sometimes normalizing the name of the routine and sometimes not, and removing the ensemble name when a [namespace ensemble] is involved. A future version of Tcl should make this more consistent. ** Synopsis ** : '''`info [level]`''' ?''`number`''? ** Description ** If ''number'' is specified, `[info] levels` returns a list consisting of words of the command for the level indicated by ''number''. A number greater than `0` indicates the level identified by that number. `0` indicates the current level, `-1` indicates one level prior to the current level, `-2` indicates the level prior to that one, and so on. If ''number'' is not specified, `[info] level` returns a number indicating the current [level], i.e. the level from which `[info] level` was called. `0` is top level, and each subsequent level is incremented by 1. ** Discussion ** [MGS] 2003-09-09: '''`info level 0`''' does not return values for optional arguments (if they have not been specified): ====== proc foo {bar {baz NULL}} { puts "info level 0 = \[[info level 0]\]" } # example1 foo abc def # example2 foo abc ====== prints: ======none info level 0 = [foo abc def] info level 0 = [foo abc] ====== [DGP] Correct. `info level $level` returns the substituted list of values that make up the actual command as evaluated. To get values for non-specified default arguments, you have to do quite a bit more work using `[info args]` and `[info default]`. This proc will print out info for all args in the calling proc ('''note''': does not handle being called from global level). ====== proc arginfo {} { set proc [lindex [info level -1] 0] set which [uplevel [list namespace which -command $proc]] puts "proc \[$which\]" set i -1 foreach arg [info args $which] { incr i set value [uplevel [list set $arg]] if { [info default $which $arg def] } { puts " arg\[$i\] \[$arg\] = \[$value\] default = \[$def\]" } else { puts " arg\[$i\] \[$arg\] = \[$value\]" } } } # test code proc test {foo {"bar baz" "BAR BAZ"}} { arginfo } test abc test abc def ====== which prints the output: ======none proc [::test] arg[0] [foo] = [abc] arg[1] [bar baz] = [BAR BAZ] default = [BAR BAZ] proc [::test] arg[0] [foo] = [abc] arg[1] [bar baz] = [def] default = [BAR BAZ] ====== ** Recursive lambda invocation ** [AMG]: [[info level 0]] is useful for writing a lambda (anonymous procedure invoked using [apply]) that can recursively call itself despite not having a name. See [https://wiki.tcl-lang.org/page/apply#86eba022562d2be62c0c1ac21610b579c8ab0d718f388560dd49538c1dcc88c2] for an example. **Interaction with namespace ensemble** [AMG]: The name of the [namespace ensemble] does not appear in the return value of [[info level 0]]. ====== % namespace eval foo { namespace export * namespace ensemble create } % proc foo::bar {} {info level 0} % foo bar bar ====== I believe this happens for the same reason the namespace name is omitted from the following: ====== % namespace eval foo {} % proc foo::bar {} {info level 0} % namespace eval foo {bar} bar ====== To recover the full name of the current command, use [namespace origin]: ====== % namespace eval foo { namespace export * namespace ensemble create } % proc foo::bar {args} { namespace origin [lindex [info level 0] 0] } % foo bar ::foo::bar % namespace eval foo {bar} ::foo::bar ====== [PYK] 2022-03-24: In the script above `[namespace which]` would be better than `[namespace origin]` because the intent to fully qualify the nam of the procedure, not to trace an imported name back to its origin. Of course, sometimes `[namespace origin]` is exactly what is desired. It's just not a synonym for `[namespace which]`. See also: [How was I invoked?] <> Command | Tcl syntax