A procedure is a [routine] that has a name that can be used as the first [word] in a [command]. [proc] creates a new procedure, and so do the [C] functions `Tcl_CreateObjCommand()` and friends. `[info commands]` provides a list of available procedures, and `[info procs]` provides a list of available procedures that were created by `[proc].` ** See Also ** [apply]: [command]: [Creating Commands]: Enumerates and compares the procedures that create procedures. [Lambda in Tcl]: Unnamed/anonymous procedures. [Local procedures]: A discussion on limiting the lifespan of a procedure inside another procedure. [Printing proc sequence]: A mechanism to trace procedure calls. [Procedure calling timed]: Timing procedure calls. [Runtime creation of procs]: [Wrapping a procedure]: Wrap a procedure and call the original, which is stored in `$next`, at any time [wrapping commands]: Various approaches to wrapping procedures. ** Description ** A '''procedure''' has name in a certain [namespace], and can only be found when that namespace is in the [namespace%|%resolution path]. Whereas as [script] is [eval%|%evaluated], a procedure is called. When a procedure is called, a new [level] is created to hold the variables local to that call, and that namespace [namespace current%|%current namespace] becomes the [namespace current%|%current namespace]. Arguments to the procedure are available as variables at in the new level. See [global] or [variable] or [upvar] on how to "import" variables from upper scopes. A procedure is like a function in that it always returns a value. When the purpose of a procedure is only to produce a side effect, its value is usually the empty string. If there is no explicit `[return]`, then the value of the last command is the value of the procedure. ** A Procedure Always Has a Name ** When a procedure is created from within the body of another procedure, it is bound to the given name in a namespace, remains, even after evaluation at the current level has completed, until it is deleted or its namespace is deleted. There is no way to create a "local" procedure at the current [level]. ====== namespace eval foo { proc one {} { puts -nonewline {Eat } proc two {} { puts -nonewline {more } proc three {} { puts chicken. } } } } foo::one foo::two foo::three ====== ** The Empty Name ** [AMG] [PYK]: The name of a procedure can even be the empty string, `{}`, but this has a weird interaction with `[rename]` and the way we abuse it for deleting procs. ====== proc {} {} { puts "my name is [info level 0]" } {} ;# -> my name is {} rename {} {} catch {{}} msg einfo puts hello puts $msg ;# -> invalid command name "" ====== Also strange: you can create a proc named by the empty string, `{}`, but you can't use [rename] to move it. [DKF]: You can, but only by renaming to a fully-qualified name, like `::`. ** Illegal Names ** Except to separate namespace parts the namespace separator string, `::`, cannot occur in the name of a procedure. This is considered an unfortunate development by some Tcl programmers: If the notation for a procedure name was a list, it would have remained possible to give a procedure any name at all. See also [CMcC%|%CMcC's] comments in the [Tcl Chatroom], 2014-11-28. ** Naming Hacks ** Almost any string is potentially valid proc name. [RS]: "Any string" includes things that look like array elements (but aren't), with which you can emulate '''"[arrays of function pointers]"''': ====== % proc f(1) {} {puts hello} % proc f(2) {} {puts world} % proc f(3) {} {puts again} % for {set i 1} {$i<=3} {incr i} {f($i)} hello world again ====== And a certain introspection is possible too: ====== info proc f(*) => f(1) f(2) f(3) ====== Update 2002-11-15: You don't have to stop at simulating - you can just have [arrays of function pointers]! ---- A procedure name that starts with a hash character `#` can be called by somehow ensuring the `#` isn't the first character: ====== proc #test {} {puts [lindex [info level 0] 0]} \#test ;# -> #test {#test} ;# -> #test \x23test;# -> #test [namespace current]::#test ;# -> ::::#test ====== Remember that comments are detected prior to the evaluation of a script. `#` has no importance when commands are being ''evaluated''. ** Page Authors ** [RS]: [PYK]: <> Glossary