How was I invoked?

Consider this example:

proc show_invocation {} {
    return [info level -1]
}


proc a args {
    puts {Beginning of a.}
    puts [show_invocation]
}


proc b args {
    a x y z
}

proc c args {
    b 1 2 3
}

c skip-to-my-lou

It has output

Beginning of a.
a x y z

In English words, this illustrates that a proc can report on the command-line which invoked it. In particular, this provides a base for introspection on the proc call-stack, coded in "Printing proc sequence", "A basic debugger", "List the call stack", and perhaps elsewhere.


wdb: Exactly that's the way the OO system obj works: an object is a reference to the base procedure called _root-object_, and is created by namespace import ::obj::class::${classname}::_root-object_, then renamed to something like ::obj::inst::new-name. The reference is located in a namespace ::obj::inst; the name originally called is used as object identifier.

Example:

% set c
::obj::inst::4
% namespace origin $c
::obj::class::curve::_root-object_
% sourceCode $c
proc ::obj::class::curve::_root-object_ {{method ::return} args} {
     $method [lindex [::info level 0] 0] {*}$args
   }
% 

Lars H: An alternative solution for this kind of thing is to make the instance command an interp alias to the _root-object_ command, and include the instance name in the command prefix for this alias. In the above example, that would amount to roughly

 interp alias {} ::obj::inst::4 {} ::obj::class::curve::_root-object_ ::obj::inst::4
 proc ::obj::class::curve::_root-object_ {self {method ::return} args} {
      $method $self {*}$args
 }

(could almost make the _root-object_ command an ensemble with parameters as well to further speed up the dispatch, but that won't let you omit the method name). Important difference: With the alias technique, the "self" value stays the same if the object command is renamed, whereas with the info level technique it changes to match the new command name. Whether this is a pro or con depends on how you use it.

wdb When making obj, the drawback of objects not to be renameable I took as a bearable one. My intention was maximum speed on generating multiple, partially just once-used local objects which not even are bound to variables.


There's more, though: with 8.5, it becomes possible to write

package require Tcl 8.5

proc show_complete_invocation {} {
    array set frame [info frame -2]
        # Memory leak ahoy!  In non-toy code, the file 
        # handle deserves its [close].
    set lines [split [read [open $frame(file)]] \n]
    return [lindex $lines [expr $frame(line) -1]]
}


proc a args {
    puts "Beginning of a."
    puts [show_complete_invocation]
}


proc b args {
    a x y z
    set x [a b c d]
}

proc c args {
    b 1 2 3
}

c skip-to-my-lou

The output of this script is

Beginning of a.
      a x y z
Beginning of a.
      set x [a b c d]

While this is a bit fragile in that it requires a few more lines to handle dynamic proc definitons and other complications, it should at least hint at the possibilities of this sort of introspection.

Interaction with namespaces

AMG: See the info level page for more information on how to get the name of the current command even when namespaces are in play.