Tcl provides several commands which create commands and script evaluation contexts. The purpose of this page is to enumerate and classify those commands. * [[[proc]]] creates a Tcl script based procedure (function) which can be defined to have a fixed or variable number arguments, with default values for the fixed arguments. * [[[apply]]] creates an anonymous command * [[[interp] create]] creates a named slave interp command * [[[interp] alias]] creates a named alias to another command * [[[thread] create]] creates an opaque token associated with a thread * [[[namespace ensemble]]] creates a namespace command from a namespace * [[[class] create] creates a named class command * [[$class create]] creates an opaquely named object instance command * [[[coroutine]]] creates a named coroutine command * [Tcl_CreateObjCommand] (and friends, see manual pages [http://www.tcl.tk/man/tcl8.6/TclLib/CrtCommand.htm], [http://www.tcl.tk/man/tcl8.6/TclLib/CrtObjCmd.htm], [http://www.tcl.tk/man/tcl8.6/TclLib/NRE.htm]) is the C API for creating a command object in a specific Tcl interpreter. ---- %|generator|cmd?|#args|invocation|destructor|rename?|% &|proc|yes|any|by name||yes|& &|[coroutine]|yes|1|by name||yes|& &|Tcl_CreateObjCommand|yes|any|by name|''see man page [http://www.tcl.tk/man/tcl8.6/TclLib/CrtObjCmd.htm]''|yes|& &|[namespace] ensemble|yes|any|by name|[namespace] delete|yes|& &|class create|yes|any|by name|$class destroy|yes|& &|$class create|yes|any|by name|$obj destroy|yes|& &|interp alias|yes|any|by name|interp alias|yes|& &|interp create|yes|any|$interp eval|$interp destroy|yes|& &|thread::create|no|any|thread::send|thread::release|no|& &|apply|no|any|by reference|''implicit''|no|& Legend for above table: %|Column|Description|% &|generator|what command generates an instance of this form?|& &|cmd?|does this form construct a command?|& &|#args|how many args does the '''constructed''' form take?|& &|invocation|how is this form invoked?|& &|destructor|what explicit destructor disposes of this form?|& &|rename?|does [[rename $name {}] destroy this form?|& ---- ** Observations ** The generation of commands appears to be a means of invoking the form and of controlling the resources associated with the form. There are two exceptions: In the case of [apply], resources are associated with a value, and the lifetime of the generated form is tied to that of the value. In the case of [thread], explicit refcounting is employed ([MS] '''I wonder about this: is it a bug?'''). In all other cases [[[rename] $name {}] destroys both the command and its associated form. In the case of [namespace ensemble]s, that is the ''main'' method of destroying the command (that it gets destroyed when the namespace is destroyed is more of a side-effect; also note that several ensembles can have the same namespace). [MS] notes that all 1-commands are 2-commands, independently of the the way a 1-command was created. Under the covers, they are all created by Tcl_CreateObjCommand (or one of its brethren). In particular: all 1- and 2-commands are invoked by name, and all 1- and 2-commands are destroyed by [rename]ing them to {}. (Here, a 1-command is a conceptual command as described by this Wiki page, and a 2-command is a mundane Tcl command. Things get tricky when we use the same word to describe two extremely closely related but not precisely identical concepts!) ** Irregularities ** [interp]-created commands duplicate functionality available through [interp], to control interp resources. It would be more consistent with the other forms if $interp args were passed directly into the interp as if [[interp eval]]'d. [coroutine]-created commands are the only forms restricted to single args. [NEM] notes that coroutines are not general commands, but rather a communication and concurrency primitive. The nearest equivalent are channels, which do indeed take only a single argument (via [puts]). [AMG]: With both coroutines and channels, you can create wrapper procs to encode/decode the communication protocol. For coroutines, the protocol is datagram-oriented: each datagram is one Tcl word. For channels, the protocol is stream-oriented. [Lars H]: Still, now that coroutines are commands, they might as well try to act like it. Had the intention been that they should only be a "communication and concurrency primitive", then an ensemble like [chan] with subcommand such as * '''coroutine create''' ''cmd'' ?''arg'' ...? —— née [coroutine] * '''coroutine interact''' ''coro'' ''datagram'' —— née ''coro datagram'' * '''coroutine destroy''' ''coro'' —— née [rename] ''coro'' "" * '''coroutine exists''' ''coro'' —— née `string length [[namespace which `''coro''`]]` * '''coroutine current''' —— née [info coroutine] * '''coroutine eval''' ''coro'' ''script'' —— "[uplevel] into a coroutine", doesn't exist (yet) would seem more appropriate. <> Internals