proc - Create a Tcl procedure proc name arguments body http://www.tcl.tk/man/tcl/TclCmd/proc.htm The proc command creates a new Tcl procedure named ''name'', replacing any existing command or procedure there may have been by that name. Whenever the new command is invoked, the contents of ''body'' will be executed by the Tcl interpreter. Normally, name is unqualified (does not include the names of any containing namespaces), and the new procedure is created in the current namespace. If name includes any namespace qualifiers, the procedure is created in the specified namespace. ''Arguments'' specifies the formal arguments to the procedure. It consists of a list, possibly empty, each of whose elements specifies one argument. Each argument specifier is also a list with either one or two fields. If there is only a single field in the specifier then it is the name of the argument; if there are two fields, then the first is the argument name and the second is its default value. '''If the procedure doesn't execute an explicit return, then its return value is the value of the last command executed in the procedure's body'''.(From: Tcl Help) ---- Redefining an existing proc occurs silently and may result in unsuspected errors (or even security breaches) if the proc is not carefully constructed. You can detect this type of error by [overloading proc] with a [Guarded proc]. ---- For a discussion on limiting the lifespan of a proc inside another proc, see [Local procedures] ---- For unnamed/anonymous procedures see [Lambda in Tcl] and [Steps towards functional programming]. ---- '''Order of arguments''': It is not specifically documented in the man page, but a proc's arguments must be defined to occur in the following sequence: * zero or more undefaulted arguments * zero or more defaulted arguments * optionally the special literal ''args'' argument; its appearance as the last argument results in the possible collection of additional arguments into a list called '''args'''. While you may name any proc argument ''args'', it won't be initialized with the special accumulating effect unless it is the last argument variable in the proc's argument list. '''Note''' With Tcl 8.4 you can do silly things with defaulted args: proc defaultargs {{def a} undef} \ { puts "def \"$def\", undef \"$undef\"" } defaultargs x y -> def "x", undef "y" catch {defaultargs x} msg puts $msg -> wrong # args: should be "defaultargs ?def? undef" ---- See http://www.changhai.org/contents/technology/programming/tcltricks.html for a discussion of Tcl proc's default argument capability. ---- See [Proc to bytecodes: when, how does it happen]. [Printing proc sequence] implements a mechanism to trace what procs are called. [Procedure calling timed] discusses timing proc calls. ---- Note that ''name'' may be any string. However, note that due to the silent replacement mentioned above, if in a Tk application you were to code: proc . {} {} you will find that you have destroyed the default toplevel, mostly causing the app to exit. This is because each widget created has a proc-equivalent (with the name of the widget) created. Defining a proc of the name of any existing widget is going to result (in the very best of cases) potentially strange behavior and, in worse cases, catastrophe. ---- [AMG]: The proc name can even be "", but this has a weird interaction with [[[rename]]] and the way we abuse it for deleting procs. % proc "" {} {puts "my name is [info level 1]"} % "" my name is {} % rename "" "" % "" empty command name "" That's strange: the no-such-command error message is different than the usual "invalid command name." Also strange: you can create a proc named "" but you can't use [[[rename]]] to do it. ---- [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]! [MG] You can also define procs with names starting with the hash character (#) which makes them completely uncallable, as the Tcl parser evaluates it as a comment rather than a command. Whether or not there'd be any reason to do so (aside from "commenting out" a particular proc quickly), I'm not really sure, but I thought it was an interesting quirk. [Lars H]: No, a name starting with a # doesn't render a procedure impossible to call. Consider % proc #test {} {info level 1} % \#test #test % {#test} #test Remember that comments are detected before a command is split into words. # has no importance when commands are being ''evaluated''. [MG] wasn't aware you could do that - I guess my understanding of how and when comments were checked for was a little off. Will have to read into that some more in the future... :) ---- [DKF] - 16-Jul-2003 - Here's a way to do magic "dereferencing" which C hackers might like... proc proc2 {name arglist body} { set header {} foreach a $arglist { if {[string match {\**} $a]} { append header "upvar 1 \${$a} [string range $a 1 end];" } } proc $name $arglist $header$body } Trying it out: % proc2 test {a *b c} {puts "a=$a, b=$b c=$c"} % test 1 argc 3 a=1, b=0 c=3 See also [Implicit upvar] for [RS]'s take, [deref] for [Larry Smith]'s. ---- [schlenk] - 03-Aug-2004 - Here's a little proc to check if defaults were used or actual arguments were present, this can be handy if a default value is used as a don't care token. proc defaultvalues? {} { expr {[llength [info args [lindex [info level 1] 0]]] - ([llength [info level 1]]-1)} } Trying it out: % proc test {a {b 1} {c 2}} {puts [defaultvalues?]} % test 1 2 % test 1 2 1 % test 1 2 3 0 ---- See [Jimulation] for an overloaded [proc] that also takes a set of static variables. ---- [Silas] - 18-Aug-2005 - I think the best way to return multiple values is to use a list. For example: proc v {} { set value1 "somevalue" set value2 "anothervalue" return [list $value1 $value2] } [arjen] told me would be a good idea to use upvar. See (I haven't tested it): proc v {name1 name2} { upvar 1 $name1 n1 upvar 1 $name2 n2 set n1 1 set n2 2 } v N1 N2 puts "$N1 $N2" [RS]: The first approach, returning a list of the results, is "cleaner" in the [functional programming] sense. The [upvar] approach creates side effects as it changes the value of variables. [Lars H]: In real life, which approach is preferable varies quite a lot. There are on the whole at least three possibilities to consider: * Return the list of the results. * Return one result as the return value of the proc, and the others using [upvar]ed variables. * Return all results in variables. Taking apart a list of values returned is sometimes annoyingly cumbersome, but in other cases that list is a good thing to have. Usually it all depends on what you're going to do with the results once you've got them. One thing that is fairly easy to do using [upvar]ed variables is to provide optional results -- provide an optional argument for the name of a variable in which to pass back a result, but if such an argument is not given then don't pass the result back (perhaps avoid computing it altogether). [RS]: Taking apart a list is pretty easy with the [foreach] ... [break] idiom :) foreach {first second third} [makeThreeResults $input] break [Larry Smith] I still think [let] is more readable: let a b c @= 1 2 3 ---- [willdye] Here's a quick demo of how procs are (normally) declared in the global scope. Feel free to extend this code to also show how namespaces can make procs 'local'. % proc outer {} {puts "If a proc is declared inside another proc, is it local?" proc middle {} {puts "No. Unlike vars, proc declaration is normally global." proc inner {} {puts "If you want a local proc, just use a namespace."}}} % outer If a proc is declared inside another proc, is it local? % middle No. Unlike vars, proc declaration is normally global. % inner If you want a local proc, just use a namespace. % ---- Charles Babbage, 1864: ''Every set of cards made for any formula will at any future time recalculate that formula with whatever constants may be required. Thus the Analytical Engine will possess a library of its own.'' ---- [Procs as data structures] - [Procs as objects] - [Runtime creation of procs] - [Simple proc tracing] - [mkproc] - [If we had no proc] - [saving all procedures] ---- !!!!!! [Arts and crafts of Tcl-Tk programming] | [Tcl syntax help] | %|[Category Command] (as a part of [Tcl]) |[Category Data Structure] |% !!!!!!