summaryrefslogtreecommitdiffstats
path: root/doc/proc.n
blob: 2dc2e3b83e030db6463aa829853f6b105a66f7c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH proc n "" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
proc \- Create a Tcl procedure
.SH SYNOPSIS
\fBproc \fIname args body\fR
.BE
.SH DESCRIPTION
.PP
The \fBproc\fR command creates a new Tcl procedure named
\fIname\fR, replacing
any existing command or procedure there may have been by that name.
Whenever the new command is invoked, the contents of \fIbody\fR will
be executed by the Tcl interpreter.
Normally, \fIname\fR is unqualified
(does not include the names of any containing namespaces),
and the new procedure is created in the current namespace.
If \fIname\fR includes any namespace qualifiers,
the procedure is created in the specified namespace.
\fIArgs\fR 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, two fields or an odd number of 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 there are an odd number of fields, then the first is the argument
name and the remaining fields are extended argument specifiers.
See \fBEXTENDED ARGUMENT SPECIFIERS\fR below for details on allowed
specifiers.
Arguments with default values that are followed by non-defaulted
arguments become required arguments; enough actual arguments must be
supplied to allow all arguments up to and including the last required
formal argument.
.PP
When \fIname\fR is invoked a local variable
will be created for each of the formal arguments to the procedure; its
value will be the value of corresponding argument in the invoking command
or the argument's default value.
Actual positional arguments are assigned to formal arguments strictly in order.
Arguments with default values need not be
specified in a procedure invocation.  However, there must be enough
actual arguments for all the
formal arguments that do not have defaults, and there must not be any extra
actual arguments.
Arguments with default values that are followed by non-defaulted
arguments become de-facto required arguments, though this may change
in a future version of Tcl; portable code should ensure that all
optional arguments come after all required arguments.
.PP
Named arguments, defined with the \fB-name\fR or \fB-switch\fR extended
argument specifiers have a specific handling detailed in
\fBNAMED ARGUMENTS HANDLING\fR below.
.PP
There is an other special case to permit procedures with
variable numbers of arguments.  If the last formal argument has the name
.QW \fBargs\fR ,
then a call to the procedure may contain more actual arguments
than the procedure has formal arguments.  In this case, all of the actual arguments
starting at the one that would be assigned to \fBargs\fR are combined into
a list (as if the \fBlist\fR command had been used); this combined value
is assigned to the local variable \fBargs\fR.
.PP
When \fIbody\fR is being executed, variable names normally refer to
local variables, which are created automatically when referenced and
deleted when the procedure returns.  One local variable is automatically
created for each of the procedure's arguments.
Other variables can only be accessed by invoking one of the \fBglobal\fR,
\fBvariable\fR, \fBupvar\fR or \fBnamespace upvar\fR commands or by
using the \fB-upvar 1\fR extended argument specifier.
The current namespace when \fIbody\fR is executed will be the
namespace that the procedure's name exists in, which will be the
namespace that it was created in unless it has been changed with
\fBrename\fR.
'\" We may change this! It makes [variable] unstable when renamed and is
'\" frankly pretty crazy, but doing it right is harder than it looks.
.PP
The \fBproc\fR command returns an empty string.  When a procedure is
invoked, the procedure's return value is the value specified in a
\fBreturn\fR command.  If the procedure does not execute an explicit
\fBreturn\fR, then its return value is the value of the last command
executed in the procedure's body.
If an error occurs while executing the procedure
body, then the procedure-as-a-whole will return that same error.
.SS "EXTENDED ARGUMENT SPECIFIERS"
.VS
.PP
The following extended specifiers can be used to define an argument:
.VE
.TP
\fB-default \fIvalue\fR
.VS
Set \fIvalue\fR as the default value for the argument. It is ignored
if \fB-required 1\fR is also used.
.TP
\fB-name \fInames\fR
.VS
Defines the argument to be a named argument. \fINames\fR can be string
or a list of strings, each string being added as a potential name for
this argument. If \fB-name\fR is used several times for the same argument,
all strings are added as potential names. See \fBNAMED ARGUMENTS HANDLING\fR
below for details on named arguments.
.TP
\fB-required \fIbool\fR
.VS
Defines that the argument is required or not to be set by the caller.
If \fIbool\fR is true, it is required to be set and any default value
is ignored. It is the default handling for non-named argument
without a default value.
If \fIbool\fR is false, it is not required to be set and the related
argument will be left unset if there is no default value. It is the
default handling for named argument.
.TP
\fB-switch \fIswitches\fR
.VS
Defines the argument to be a flag/switch named argument. \fISwitches\fR
is a list of potential switches for this argument.
Each switch is defined either as a
single string or as a list of a string and a value. When the switch is
defined as a single string, the string is used as both the switch name
and the switch value.
When the switch is defined as a list of two entries, the first one is
the switch name and the second one is the switch value. If \fB-switch\fR
is used several times for the same argument, all switches are added
as potential switches. On call-site, the related switch value will be
set on the argument if one of the switch names is used.
See \fBNAMED ARGUMENTS HANDLING\fR below for details on named arguments.
.TP
\fB-upvar \fIlevel\fR
.VS
When defined, this will cause the related variable, rather than taking
the parameter value, to become an alias to the variable in the frame
at level \fIlevel\fR corresponding to the parameter value. \fILevel\fR
may have any of the forms permitted for the \fBupvar\fR command.
This specifier is incompatible with the \fB-switch\fR specifier.
.VE
.SS "NAMED ARGUMENTS HANDLING"
.VS
.PP
Named argument are arguments defined using the \fB-name\fR or \fB-switch\fR
extended argument specifiers. They have a special handling on call-site.
All contiguous named arguments, called named group, are handled together,
they are not required to be declared in order, can be omited or declared
multiple times. The handling of a named group is started when previous
formal arguments have been assigned.
Each named parameter uses a string starting with a dash character, followed
by the name of the related argument. If it is not a switch argument, it is
followed by the value to assign to the formal argument. The handling of
a named group is ended if the next parameter is a multiple-elements list,
does not start with a dash or is the special \fB--\fR keyword. Remaining
parameters, except the \fB--\fR keyword if used, are then assigned to
following positional arguments using the default handling.
.VE
.SH EXAMPLES
.PP
This is a procedure that takes two arguments and prints both their sum
and their product. It also returns the string
.QW OK
to the caller as an explicit result.
.PP
.CS
\fBproc\fR printSumProduct {x y} {
    set sum [expr {$x + $y}]
    set prod [expr {$x * $y}]
    puts "sum is $sum, product is $prod"
    return "OK"
}
.CE
.PP
This is a procedure that accepts arbitrarily many arguments and prints
them out, one by one.
.PP
.CS
\fBproc\fR printArguments args {
    foreach arg $args {
        puts $arg
    }
}
.CE
.PP
These procedures are a bit like the \fBincr\fR command, except they
multiply the contents of the named variable by the value, which
defaults to \fB2\fR. The second procedure uses extended argument
specifiers and especially the \fB-upvar\fR specifier:
.PP
.CS
\fBproc\fR mult {varName {multiplier 2}} {
    upvar 1 $varName var
    set var [expr {$var * $multiplier}]
}

\fBproc\fR mult {{var -upvar 1} {multiplier -default 2}} {
  set var [expr {$var * $multiplier}]
}
.CE
.PP
This is a procedure that uses named argument for the first two
arguments. \fILevel\fR defaults to \fB1\fR and can be defined
using either \fB-level \fIlevelValue\fR or one of the switches
\fB-debug\fR (\fB0\fR) or \fB-error\fR (\fB3\fR). \fITime\fR
can be defined using either \fB-time \fItimeValue\fR or
\fB-timestamp \fItimeValue\fR. If none is used, \fItime\fR will
be left unset in the procedure.
.PP
.CS
\fBproc\fR log {
    {level -name level -switch {{debug 0} {error 3}} -default 1}
    {time -name {time timestamp}}
    {message} } {
  if {![info exists time]} {set time [clock seconds]}
  array set levels {0 DEBUG 1 INFO 2 WARN 3 ERROR}
  puts "[clock format $time] : $levels($level) : $message"
}

% log -level 2 "Warning..."
Sun Apr 23 20:29:41 UTC 2017 : WARN : Warning...
% log -timestamp 946684800 -debug -- -Y2K-
Sat Jan 01 00:00:00 UTC 2000 : DEBUG : -Y2K-
.CE
.SH "SEE ALSO"
info(n), unknown(n)
.SH KEYWORDS
argument, procedure
'\" Local Variables:
'\" mode: nroff
'\" End: