TCL Basics

Download as pdf or txt
Download as pdf or txt
You are on page 1of 45

Resources:

Book: Practical Programming in Tcl and Tk by Brent B. Welch


http://zetcode.com/lang/tcl/

############
TCL stands for Tool Command Language.
Tcl is a string based scripting language. The source code is
compiled into bytecode, which is later interpreted by the Tcl
interpreter. It was created by John Osterhout in 1988. The
purpose was to create a language which is easily embeddable
into applications.
To start TCL shell in Linux terminal: tclsh
To run TCL sripts: tclsh <file_name.tcl>
############
Tcl uses the pound character, #, for comments.
puts stdout {Hello, World!}
=>Hello, World!
Curly braces are used to group words together into a single
argument.
############

The set command is used to assign a value to a variable.


Variable names can be any length but it is case sensitive. It is
not necessary to declare Tcl variables before you use them. The
interpreter will create the variable when it is first assigned a
value.
set var 5
=>5
set b $var
=>5
############
A nested command is delimited by square brackets []. The Tcl
interpreter takes everything between the brackets and evaluates
it as a command.
############
The Tcl interpreter itself does not evaluate math expressions. Tcl
just does grouping, substitutions and command invocations. The
expr command is used to parse and evaluate math expressions.
expr 7.2/4
=>1.8
The math syntax supported by expr is the same as the C
expression syntax.
############

Nested command example:


set x 7
set len [expr [string length foobar] + $x]
=>13
expr operate more efficiently by grouping the entire expression
in curly braces.
set len [expr {[string length foobar] + $x}]

############
A common use of backslashes is to continue long commands on
multiple lines. This is necessary because a newline terminates a
command.
Continuing long lines with backslashes:
set totalLenght [expr [string lenght $one] + \
[string length $two]]

############
Double quotes and curly braces are used to group words together
into one argument. The difference between double quotes and
curly braces is that quotes allows substitution to occur in the

group, while curly braces prevents the substitutions. This rule


applies to command, variable, and backslash substitutions.
set s Hello
=>Hello
puts stdout "The length of $s is [string length $s]."
=>The length of Hello is 5.
puts stdout {The length of $s is [string length $s].}
=>The length of $s is [string length $s].

############
The square bracket syntax used for command substitution does
not provide grouping.
The following is the redundant use of double quotes:
puts stdout "[expr $s + $p]"
############
Tcl uses the proc command to define procedures. Once defined,
a Tcl procedure is used just like any of the other built-in Tcl
commands. The basic syntax to define a procedure is:
proc name arglist body
The first argument is the name of the procedure being defined.
The second argument is a list of parameters to the procedure.

The third argument is a command body that is one or more Tcl


commands.
The procedure name is case sensitive, and in fact it can contain
any characters. Procedure names and variable names do not
conflict with each other.
Defining a procedure
proc Diag {a b}{
set c [expr {sqrt($a*$a + $b*$b)}]
return $c
}
puts "The diagonal of a 3,4 right triangle is [Diag 3 4]"
=>The diagonal of a 3,4 right triangle is 5.0

The procedure can also be written as:


proc Diag {a b}{
return [expr {sqrt($a*$a + $b*$b)}]
}
The return command is used to return the result of the
procedure. The return command is optional in this example
becasue the Tcl interpreter returns the value of the last command

in the body as the value of the procedure. So, the could be


reduced to:
proc Diag{a b}{
expr {sqrt($a*$a + $b*$b)}
}

############
A while loop to compute factorial
proc Factorial {x}{
set i 1; set product 1
while {$i<=$x}{
set product [expr {$product*$i}]
incr i
}
return $product
}
Factorial 10
=>3628800

############
############
A recursive definition of factorial
proc Factorial {x}{
if{$x <=1}{
return 1
}else{
return [expr {$x*[Factorial [expr {$x - 1}]]}]
}
}
############
You can delete a variable with unset command:
unset varName1
Any number of variable names can be passed to the unset
command. However, unset will raise an error if a variable is not
already defined, unless the -nocomplain is given. Use -- to unset
a variable named -nocomplain.
############
The existence of a variable can be tested with the info exists
command.

############
Command arguments are separated by white space, unless
arguments are grouped with curly braces or double quotes.
Grouping with curly braces, {}, prevents substitutions.
Grouping with double quotes, " ", allows substitutions.
Grouping decisions are made before substitutions are performed,
which means that the values of variables or command results do
not affect grouping.
Square brackets, [], cause command substitution. Everything
between the brackets is treated as a command, and everything
including the brackets is replaced with the result of the
command. Nesting is allowed in square brackets.
############
linsert = inset elements into a list.
lindex = Fetch an element of a list.
lappend = Add element to the end of a list.
join = Concatenate list elements with a given separator string.
global = Declare global variables.
glob = Expand a pattern to matching file names.
gets = Read a line of input from an I/O stream.
format = Format a string similar to C sprintf.

foreach = Loop construct over a list, or lists, of values.


eof = Check for end of file.
error = Raise an error.
append = Append arguments to a variable's value. No spaces
added
after = Schedule a Tcl command for later execution.
clock = Get the time and format date strings.
close = Close an open I/O stream.
list = Create a list out of the arguments.
llength = Return the number of elements in a list.
lreplace = Replace elements of a list.
lsearch = Seach for an element of a list that matches a pattern.
lset = Set an element in a list.
pid =

Return the process ID.

regexp = Match regular expressions.


regsub = Substiture based on regular expressions.
split = Chop a string up into list elements.
switch = Test several conditions.
time = Measure the execution time of a command.

trace =

Monitor variable assignments.

############
set str1 "ksadfal"
set str2 "jaskdfja"
string equal -nocase $str1 $str2
It will return 1 if str1 and str2 are equal. Here -nocase is used for
case insensitive comparison.

############
string first $str1 $str2
It will return the index of the first occurrence of str1 in str2. The
index count from zero. If str1 is not found in str2 then it will
return -1.

string last $str1 $str2


It will return the index of the first occurrence of str1 in str2 from
the last. The index count from zero. If str1 is not found in str2
then it will return -1.
############
string index $str1 3

It will return the character in str1 at index 3. Use end for the last
character.
string index $str1 end
string index $str1 end-1
############
string length $str1
It will return the number of characters in string str1.
############
The map command takes two arguments: a list and a Tcl
command. For each element in the list, it executes the given
command with the list element appended as an additional
arguments. With the results of all the commands it generates a
new list, and then returns this list as its results.
string map {abc def} abcabcabc
=>defdefdef
Tcl has mapped each occurrence of the string "abc" and replaced
it with the string "def".

############
string match command returns 1 if str matches the pattern, else
0.It implements glob-style pattern matching.

* match any number of characters.


? match exactly one character.
[chars] match any character in chars.

sring match a* alpha


=>1

To match all two-letter strings:


string match ?? xy
=>1

To match all strings that being with either a or b:


string match {[ab]*} cello
=>0
You can include more than one range in a set. Any letter, digit,
or the underscore is matched with:
string match {[a-zA-Z0-9_]} $char

If you need to include a literal *,?, or bracket in your pattern,


preface it with a backslash:

string match {*\?} what?


=>1
In this case the pattern is quoted with curly braces because Tcl
interpreter is also doing backslash substitutions. Without the
braces, you would have to use two backslashes. They are
replaced with a single backslash by Tcl before string match is
called.
string match *\\? what?

############
string range str i j
Returns the range of characters in str from i to j.
string range "abcdefg" 3 5
=>def
############
string repeat "ab" 3
=>ababab
############
string replace "this is a bad example" 10 12 good
=>this is a good example

string map {bad good} "this is a bad example"


=>this is a good example
############
string tolower "15 Charing Cross ROAD"
=>15 charing cross road

string toupper "Watch out!"


=>WATCH OUT!

string toupper "Watch out!" 2 4


=>WaTCH out!

string totitle "hello this is an example."


=>Hello this is an example.

string trim caasadcxxxbabopqab abc


=>sadcxxxbabopq

string trimleft caasadcxxxbabopqab abc


=>sadcxxxbabopqab
############
string first th "There is the tub where I bathed today"
=>9
It searches the second string to see if there is a substring that is
identical to the first string. If so, it returns the index of the first
character in the leftmost matching substring; if not, it returns -1.
The search starts from the beginning of the second string unless
you also provide an argument specifying the character index
where the search should start. Eor example in the following
example teh start index is 12.
string first th "There is the tub where I bathed today" 12
=>27

The command string last is similar except it returns the starting


index of the rightmost matching substring:
string last th "There is the tub where I bathed today"
=>27
############

The command string compare takes two additional string


arguments and compares them, returning 0 if the strings are
identical, -1 if the first string sorts before the second, and 1 if the
first string is after the second in sorting order:
string compare Michigan Minnessota
=>-1
string compare Michigan Michigan
=>0
The string equal command does a simple string comparison of
two strings, returning 1 if they are exactly the same and 0 if they
aren't. Both string compare and string equal are case-sensitive
unless you specify the -nocase option. You can also provide an
optional -length option to specify that only the first length
characters be used in the comparison:
string equal cat cat
=>1
string equal dog Dog
=>0
string equla -nocase dog Dog
=>1
string equal -length 3 catalyst cataract

=>1
############
You can perform a simple string replacement with the string
replace command. It accepts a string as an argument along with
the beginning and ending indices of a sequence of characters to
delete, as well as an optional string argument to insert in their
place:
string replace "San Diego, California" 4 8 "Francisco"
=>San Francisco, California
string replace "parsley, sage, rosemary, and thyme" 0 8
=>sage, rosemary, and thyme
############
Tcl's format command provides facilities like those of the sprintf
procedure from the ANSI C library.
format "The square root of 10 is %.3f" [expr sqrt(10)]
=>The square root of 10 is 3.162
############
The append command takes a variable name as its first argument
and concatenates its remaining arguments onto the current value
of the named variable. The variable is created if it does not
already exist:

set foo z
append foo a b c
set foo
=>zabc
append x "some new stuff"
is always faster than this:
set x "$x some new stuff"
############
A Tcl list is a sequence of values.
A list in Tcl consists of a string whose items are separated by
white space.
A list has its elements separated by white space. Braces or
quotes can be used to group words with white space into a single
list element.
To assign a list to a variable we can do this,
set list1 {A B C D E}
or this,
set list1 [list A B C D E]
The second method is better because the use of the list command
makes it much clearer that a list is being created. To print a raw
list to the console we use the puts command,

puts "The contents of list1 are: $list1"

It is possible for one list to have another list embedded within it,
for example,
set list1 [list A B [list 1 2 3] C D E]
A list may also contain consecutive lists, for example,
set list1 [list DOG CAT MULE]
set list2 [list dog cat mule]
set list3 [list $list1 $list2]

############
To step through a list the foreach command is used,
foreach item $list1 {
puts $item
}
Although the use of foreach, shown above, works well when
printing a simple list it fails to print items contained within
embedded lists. A partial solution to this problem is to
encapsulate the list handling code within a procedure.
proc printlist { inlist } {

foreach item $inlist {


puts $item
}
}
By making the procedure recursive it can the items in an
embedded list correctly.
proc printlist { inlist } {
foreach item $inlist {
# recurse - go into the sub list
if { [llength $item] > 1 } {
printlist $item
} else {
puts $item
}
}
Note the use of the llength command to check if an item consists
of sub items. Finally, to use this procedure,
set list1 [list A B [list 1 2 3] C D E]
printlist $list1
############

set l3 [split "1.2.3.4" .]


Some Tcl commands return a list as a result. In the above code
line, the split command returns a list of numbers generated from
a string.

############
set nums { 1 2 3 4 5 6 7 }
puts [llength $nums]
The llength command returns a length of the list.

puts [lindex $nums 2]


The lindex command returns an item on the third position of the
list. The positions in Tcl lists start from 0.

puts [lrange $nums 1 3]


The lrange command returns a subset of the list.
############
set nums {4 5 6}
puts $nums
456

lappend nums 7 8 9
puts $nums
456789
The lappend appends data to the list.

puts [linsert $nums 0 1 2 3]


123456789
The linsert inserts elements at a given index. The first number is
the index. The remaining values are numbers to be inserted into
the list. The command creates a new lists and returns it. It does
not modify the original list.

puts $nums
456789
############
set animals1 { lion eagle elephant dog cat }
set animals2 { giraffe tiger horse dolphin }

set animals [concat $animals1 $animals2]

puts $animals
lion eagle elephant dog cat giraffe tiger horse dolphin

The concat command is used to concatenate (add) two lists. The


above line joins two lists and the new list is set to the animals
variable.

puts [lsearch -exact $animals eagle]


1
With the lsearch command we look for an eagle in the list. With
the -exact option we look for an exact match. The command
returns the index of the first matching element. Or -1 if there is
no match.

puts [lreplace $animals 3 4 buffalo crocodile]


lion eagle elephant buffalo crocodile giraffe tiger horse dolphin

The lreplace command replaces dog and cat with buffalo and
crocodile.

############
set names { John Mary Lenka Veronika Julia Robert }
set nums { 1 5 4 3 6 7 9 2 11 0 8 2 3 }
To sort list elements, we can use the sort command. The
command does not modify the original list. It returns a new
sorted list of elements.
We have two lists. In the first we have strings, in the second
numbers.
The default sorting is the ascii sorting. The elements are sorted
by their positions in the ascii table.
puts [lsort $names]
John Julia Lenka Mary Robert Veronika

puts [lsort -ascii $names]


John Julia Lenka Mary Robert Veronika

puts [lsort -ascii -decreasing $names]


Veronika Robert Mary Lenka Julia John

puts [lsort -integer -increasing $nums]


0 1 2 2 3 3 4 5 6 7 8 9 11

puts [lsort -integer -decreasing $nums]


11 9 8 7 6 5 4 3 3 2 2 1 0
We treat the values as integers and sort them in increasing and
decreasing orders.

puts [lsort -integer -unique $nums]


0 1 2 3 4 5 6 7 8 9 11
We sort the elements of the list in a numerical context in
increasing order. Duplicates will be removed.
############
In Tcl there can be nested lists; list in other lists.
set nums {1 2 {1 2 3 4} {{1 2} {3 4}} 3 4}
A list with two nested lists. The second list has two additional
inner nested lists.

puts [llength $nums]


6
We determine the size of the list. The nested list is counted as
one element.

puts [llength [lindex $nums 2]]


4
In this line, we determine the size of the first nested list, which
is the third element of the main list.

puts [lindex $nums 0]


1
Here we print the first element of the main list.

puts [lindex [lindex $nums 2] 1]


2

In the above line, we get the second element of the first nested
list.

puts [lindex [lindex [lindex $nums 3] 1] 1]


4
Here we get the second element of the second inner list of the
inner list located at the 4th position of the main list. In other
words: the inner most command is executed first. The [lindex
$nums 3] returns {{1 2} {3 4}}. Now the second command
operates on this returned list. [lindex {{1 2} {3 4}} 1] returns {3
4}. Finally, the last command [lindex {3 4} 1] returns 4, which
is printed to the terminal.
############
The lset command is in some way the complement to lindex.
While lindex returns the list element at the specified index, lset
replaces the list element at the specified position with a new
value.

% set a {a b c d}
abcd
% lset a 2 X

abXd
% puts $a
abXd

Lset can directly access nested lists in a similar fashion to


lindex, specifing multiple indexes, so for example the command
"lset foobar 2 3 $newval" Will set $newvalue as third element of
the list that's the second element of the list contained inside the
variable $foobar.

lset new "a b c"


=> a b c
lset new 1 "d e"
=> a {d e} c
lset new 1 0 "g h"
=> a {{g h} e} c

lset a 1 2 newValue
or

lset a {1 2} newValue
replaces element 2 of sublist 1 with newValue.

############
split makes a list from a string by splitting the string up into list
elements.
If invoked with one argument (the string), the string is split on
whitespace
If invoked with two arguments, the second argument is used as a
set of characters to split on
If the second argument is the empty string, the string is split
between every character, resulting in a list of characters. (This is
like the old Lisp explode function.)
split
"keith:cdridjyhTp2FQ:100:1100:Keith
Waclena:/home/keith:/host/bin/zsh" :
=> keith cdridjyhTp2FQ
/home/keith /host/bin/zsh
split abcde {}
=> a b c d e

100

1100

{Keith

Waclena}

join is the inverse of split: it forms a string from a list by


inserting a particular character between each list element. For
example:
join [list 1 2 3] ,
=> 1,2,3
join
[split
"keith:cdridjyhTp2FQ:100:1100:Keith
Waclena:/home/keith:/host/bin/zsh" :] :
=>
keith:cdridjyhTp2FQ:100:1100:Keith
Waclena:/home/keith:/host/bin/zsh
############
The lrmdups command removes repeated or duplicate items
from a list. The resulting list will be sorted in lexicographic
order.

The lempty command returns 1 if its argument list is the empty


list, or 0 otherwise. This is exactly equivalent to comparing the
candidate list to the empty string for equality, but lempty reads
better and is slightly simpler to write:
lempty $x
expr $x == ""

The lassign command does multiple assignment of the elements


of a list to a corresponding set of variables. Any elements left
over in the list (because not enough variables were provided) are
returned as a list by lassign. For example:
lassign {1 2 3 4 5} a b c
=> 4 5
set a
=> 1
set b
=> 2
set c
=> 3
This is more efficient and much more readble than the
equivalent series of set and lindex commands.
############
lvarcat is a call-by-name version of concat. All arguments
except the first are concat'ed together onto the end of the list
stored in the variable named by the first argument.
set x [list x y]
=> x y

lvarcat x 1 2 {a b} 3
=> x y 1 2 {a b} 3
set x [list x y]
=> x y
set x [concat $x 1 2 {a b} 3]
=> x y 1 2 {a b} 3
############
lvarpush and lvarpop make it easy to use lists as stacks. lvarpush
adds a new element to the beginning of the list stored in the
named variable (the variable is created if necessary):
set x
Error: can't read "x": no such variable
lvarpush x 1
=>
lvarpush x 2
=>
lvarpush x 3
=>
set x
=> 3 2 1

Note that lvarpush returns no value (or equivalently, it always


returns the empty string as it's result).
lvarpop removes the first element from the list stored in the
variable named by its argument, and returns that element as its
result:

lvarpop x
=> 3
set x
=> 2 1
lvarpop x
=> 2
set x
=> 1
lvarpop x
=> 1
set x
=>
Stacks can be implemented with set, concat and lindex, but
lvarpush and lvarpop are more readable and more efficient:

set x {}
=>
set x [concat 1 $x]
=> 1
set x [concat 2 $x]
=> 2 1
set x [concat 3 $x]
=> 3 2 1
lindex $x 0
=> 3
set x [lreplace $x 0 0]
lindex $x 0
=> 2
set x [lreplace $x 0 0]
lindex $x 0
=> 1
set x [lreplace $x 0 0]
set x

=>
Both lvarpush and lvarpop will manipulate other elements of the
list than just the first, but I recommend avoiding these forms and
using linsert and lreplace instead.
############
lmatch is similar to lsearch, but it returns not the first matching
element, but rather a list of all matching elements. Any of the
standard Tcl pattern matching options may be used to determine
how the matching is done.
############
intersect treats two list arguments as sets and returns the set (list)
which is their intersection:
intersect {a b c} {x y z}
=>
intersect {a b c} {x a c}
=> a c
intersect {a b c} {x a a a c a}
=> a c
############
intersect3 is similar to intersect, but returns a list of three results.
Call the first argument to intersect3 A and the second B. Then

the first of the three results is A - B, the second result is A


intersect B, and the third reuslt is B - A. All three result lists are
will be sorted.
intersect3 {a b c} {x a a a c a}
=> b {a c} x
############
The union Command
Returns the set theoretic union of its two arguments. Since we
are treating lists as sets, duplicates are removed.
############
Keyed lists are an Extended Tcl data structure that provides a
facility for record structures (like struct in C; record in Pascal,
structures in PL/I, etc).
Like lists, keyed lists are actually strings that obey a certain . A
keyed list is a list of name, value pairs. Each pair is itself a list,
so keyed lists are simply lists of pairs or lists of lists. Extended
Tcl provides a number of commands to manipulate keyed lists
efficiently; these commands use call-by-name to manipulate a
keyed list stored in a variable.
############
Sets a field in the keyed list to a particular value. Returns no
value. Creates the variable if necessary.

keylset x NAME {Terry Dactyl}


set x
=> {NAME {Terry Dactyl}}
keylset x ADDRESS {1492 Columbus}
set x
=> {NAME {Terry Dactyl}} {ADDRESS {1492 Columbus}}
keylset x NAME {Jerry Atric}
set x
=> {NAME {Jerry Atric}} {ADDRESS {1492 Columbus}}
############
A conditional if then else command:
if {$x == 0} {
puts stderr "Divide by zero!"
} else {
set slope [expr $y/$x]
}
############
Chained conditional with elseif:
if {$key < 0} {

incr range 1
} elseif {$key == 0} {
return $range
} else {
incr range -1
}
Any number of conditionals can be chained in this manner.
However, the switch command provides a more powerful way to
test multiple
conditions.
############
Using switch for an exact match:
switch -exact -- $value {
foo { doFoo; incr count(foo) }
bar { doBar; return $count(foo)}
default { incr count(other) }
}
############
A comment can occur only where the Tcl parser expects a
command to begin. This restricts the location of comments in a

switch command. You must put them inside the command body
associated with a pattern, as
shown here:
switch -- $value {
# this comment confuses switch
pattern { # this comment is ok }
}
############
While statement:
set i 0 ; while {$i<10} {incr i}
############
A while loop to read standard input:
set numLines 0 ; set numChars 0
while {[gets stdin line] >= 0} {
incr numLines
incr numChars [string length $line]
}
############

The foreach command loops over a command body assigning


one or more loop variables to each of the values in one or more
lists. Multiple
loop variables, which were introduced in Tcl 7.5, are a very
useful feature.
set i 1
foreach value {1 3 5 7 11 13 17 19 23} {
set i [expr $i*$value]
}
set i
=> 111546435
############
You can have more than one loop variable with foreach.
Suppose you have two loop variables x and y. In the first
iteration of the loop, x gets
the first value from the value list and y gets the second value. In
the second iteration, x gets the third value and y gets the fourth
value. This continues until there are no more values. If there are
not enough values to assign to all the loop variables, the extra
variables get the empty string as their value.

foreach {key value} {orange 55 blue 72 red 24 green} {

puts "$key: $value"


}
orange: 55
blue: 72
red: 24
green:
############
Multiple value lists with foreach:
foreach {k1 k2} {orange blue red green black} value {55 72 24}
{
puts "$k1 $k2: $value"
}
orange blue: 55
red green: 72
black : 24
############
For loop:
for {set i 0} {$i < 10} {incr i 3} {
lappend aList $i

}
set aList
=> 0 3 6 9
############
You can control loop execution with the break and continue
commands. The break command causes immediate exit from a
loop, while the
continue command causes the loop to continue with the next
iteration. There is no goto command in Tcl.
############
Until now we have ignored the possibility of errors. In practice,
however, a command will raise an error if it is called with the
wrong number of arguments, or if it detects some error condition
particular to its implementation. An uncaught error aborts
execution of a script.
The catch command is used to trap such errors. It takes two
arguments:
catch command ?resultVar?

The catch command may be used to prevent errors from aborting


command interpretation. Catch calls the Tcl interpreter
recursively to execute script, and always returns without raising

an error, regardless of any errors that might occur while


executing script.
If script raises an error, catch will return a non-zero integer
value corresponding to one of the exceptional return codes (see
tcl.h for the definitions of code values). If the messageVarName
argument is given, then the variable it names is set to the error
message from interpreting script. If optionsVarName is given,
then the variable it names is set to a dictionary describing details
of the exceptional situation.
If script does not raise an error, catch will return 0 (TCL_OK)
and set the variable to the value returned from script.
Note that catch catches all exceptions, including those generated
by break and continue, and return, as well as errors. The only
errors that are not caught are syntax errors found when the script
is compiled. This is because the catch command only catches
errors during runtime. When the catch statement is compiled, the
script is compiled as well and any syntax errors will generate a
Tcl error.

The catch command may be used in an if to branch based on the


success of a script.
if { [catch {open $someFile w} fid] } {
puts stderr "Could not open $someFile for writing\n$fid"

exit 1
}
############
The error command raises an error condition that terminates a
script unless it is trapped with thec atch command. The
command takes up to
three arguments:
error message ?info? ?code?
The message becomes the error message stored in the result
variable of the catch command.
If the info argument is provided, then the Tcl interpreter uses
this to initialize the errorInfo global variable. That variable is
used to collect a stack trace from the point of the error. If the
info argument is not provided, then the error command itself is
used to initialize the errorInfo trace.

Many Tcl commands generate an error condition when there is a


problem (command invoked with invalid arguments, runtime
error, etc). This error condition, or error for short, interrupts the
running program and causes Tcl to print an error message before
terminating. Tcl commands often generate errors in cases where,
in most programming languages, a subroutine would return a
special value that would have to checked for.

set foo
Error: can't read "foo": no such variable
############
The return command is used to return from a procedure. It is
needed if return is to occur before the end of the procedure
body, or if a
constant value needs to be returned. As a matter of style, I also
use return at the end of a procedure, even though a procedure
returns the
value of the last command executed in the body.
############

You might also like