TCLWISE
An introduction to the Tcl programming language
Sponsored Project: The Jim interpreter A small footprint implementation of Tcl |
Send a comment to the author
|
8. CONTROL CONSTRUCTS
In the last chapters we focused enough into the goal of learning how
Tcl works, that some important core command escaped our attention.
Now the reader should be familiar enough with the structure of Tcl programs
to learn some new interesting command without too efforts.
All the commands covered in this chapter are about controlling the flow
of the program. We already saw if, while and foreach, but there are other
interesting control constructs to discover.
8.1 The switch command The switch command is very useful when we want to test the value
of a string against a number of patterns, and execute a different
code based on the matching pattern. You can see switch as a special
case of if, for instance the code:
can be translated in this using switch:
As you can see the second version is more readable. In the simple form
switch takes two arguments:
switch string {pattern body pattern body ?pattern body? ...} The first argument is the string we want to test against the patterns,
the second argument is a list with pairs of pattern to match against,
and the body of the script to execute if there is a match for this pattern.
If the last pattern is the string "default", the relative body will be
executed if no one of the previous patterns matched.
That's the main idea of switch, but actually the command is a bit more
complex, because it supports another form, and a number of options that
change the way the string is matched against the patterns. This is
the complete signature of the command:
switch ?options? string {pattern body ?pattern body ...?} or, in alternative:
switch ?options? string pattern body ?pattern body ...? This second form just means that instead to pass the pattern body
pairs into a list it is also possible to pass they directly as
switch arguments. You may like this form when writing very short code
like:
But in general the first form is better from the point of view of
the indentation. Another thing to note is that switch can take
options to modify his behaviour. The supported options are:
The default matching type is -glob, this is not very comfortable because
most of the time you may want to match strings with exact matching
(i.e. using -exact). Another problem with switch options is that if
the string argument starts with a - character, it is interpreted
as an option, unless there is a -- argument just after the command name.
So, most of the time you want to use something like this:
This is the safe way to use switch. Of course if you like to use
glob style or regexp matching, you can substitute -exact with what
you need.
Starting with Tcl 8.5, switch supports two new options, they
are -matchvar and -indexvar. Both the options are about the
regexp matching style (-regexp option) and are not vital in this
stage of your Tcl experience, but be sure to check the man page if you
need to use regexp matching with switch and want to store in variables
the match or submatches of the matching pattern.
It's worth to note that like the if command, switch returns the
value of the last command executed in the matching branch, so for
instance it's possible to write something like:
The identity function is just used to return the value we are interested
to assign to the word variable if $x matches one of the patterns.
8.2 The for command The Tcl for command is modelled after the C language one, like
in many other languages. for is used to loop, i.e. to repeat the
same fragment of code multiple time, in this respect it is very similar
to the while command, but a bit more complex.
The more common use of for is to run a variable over an arithmetic
progression.
The following is an example of for loop, used to count from 0 to 9:
If you try to execute this code, the output is
up to 9. If you look at the code, it's easy to notice that for takes
four Tcl scripts as arguments, this is the signature for the for command:
for start test next body The for loop starts evaluating the start script, that in our example
is the Tcl code "set i 0". This will set the variable i to the value
of zero. The start script is evaluated only one time, as first
step of a for loop. Now the loop can start, following this rules:
The test argument is evaluated using expr, if the result is true
the body script is executed, then the next script is executed.
An interation is now completed, and the loop restart testing against
if test is true. The first time the test is false, the for loop
terminates.
The command always returns an empty string. Note that it's possible
to put every kind of Tcl script in the start, next, and body
arguments, and every kind of valid expr expression in the test
argument. For example this is an infinite loop:
Similarly it's possible to use more than a variable:
The above code will increment x by 2 and y by 3, and will stop when
the sum of the two will be 50 (after 10 iterations). In the example
the body argument is empty because the work needed to continue the
computation is in the next script.
8.3 break and continue Tcl core commands implementing looping constructs like foreach,
while, and for, support a way to exit prematurely from the loop,
or to prematurely reiterate it before all the commands of the body
of the loop are executed. In order to control this features, there are
two Tcl commands called break and continue. They are modelled
after the C programming language break and continue keywords.
The break command is the one used to prematurely exit from the loop.
It may appear at any place in the body of the loop. If there are
nested loops and the break command is executed, only the innermost
loop will terminate. In Tcl break does not take any argument, and
there is no way to specify how many levels to exit. This is an example
of code using break:
The output of the program is a sequence of numbers from 0 to 9. Note that
even if the while loop apperas to be an infinite loop (because the condition
is true being just 1, and will never change), break allows to exit from
the loop if a given condition is encountered (that the variable a contains
the value of 10).
Calling the break command outside a loop will produce an error, because
there is no loop to escape.
You may wonder how it's possible to exit multiple nexted loops if a
break command will only terminate the innermost one. This example contains
two nested loops:
In order to exit two levels, we can use the following trick:
This time in order to exit both the loops we initialize a dobreak variable
to zero, and test it every time we exit from the inner loop, calling break
again in the outside loop if it is set to 1. In the inner loop
we can use just break when we want to escape only one loop, or
set dobreak 1; break when we want to escape both.
You will hardly need to use this kind of tricks because the need to break
multiple loops is not common, but it may be useful to know how to do it
if really needed.
Note that break works exactly in the same way with for, foreach and
other looping commands.
If you are a C programmer, you may remember that in C it may
happen to have a while or for loop with a nested switch inside.
Because in C the switch requires break in order to terminate a case
you can't escape the loop from the switch using break. Instead
something like a flag variable similar to the dobreak above, or the
use of goto, is required.
In Tcl this problems does not exist because Tcl's switch does not
use the break in any way, so a break inside the switch will produce
the desidered effect of terminating the innermost loop.
The external loop will continue to run forever, because the break of the
nexted while loop will only affect the.
The continue command is similar to break, but instead to terminate
the innermost loop in execution, it will just reiterate it. It's important
to specify what to reiterate means in this context: when continue is
encountered what happens is exactly what happens if there are no longer
commands to execute in the body of the loop. In the case of a while
loop the test condition will be evaluated again, and the loop body
will be executed if it is still true. In the case of foreach the next
element(s) of the list(s) will be assigned to the foreach variable(s),
and the body will be executed again, and so on.
The following is an example of continue:
The above Tcl programm will output the numbers from 3 to 9, because
at every iteration, if $x < 3 is true, the loop will reiterate without
to execute the puts $x command.
8.4 The lack of goto In Tcl there isn't a goto command, there are many reasons to avoid
goto designing an high level programming language, actually the
author of this book have good uses for goto in C, in order to deal
with exceptions or to escape nested loops, but when programming in Tcl
it's very hard to miss a goto command. Tcl is at higher level:
there is exception handling, switch inside loops can use break to
terminate the loop, and in general working at higher level the lack
of a goto command is not an issue. Most of the times when you require
goto in C, you may want to implement a state machine in Tcl.
Still, the Tcl goal is the flexibility, in the next chapter you will learn
how it is possible to write Tcl commands implementing new control structures
in Tcl itself, including things similar to goto.
For know it can be interesting to remember that it's possible to use
foreach and break to implementing something that may resemble an unconditional
jump, like in the following code:
the foreach will iterate just one time using the variable _ in
a list composed of one element (the "_" string). When the foreach
body will call break the body will terminate.
|
Other Tcl/Tk books Index
2.1 Anatomy of a command
2.2 Grouping
2.3 Program structure
2.4 Substitution of commands
2.5 Substitution of variables
2.6 More on interpolation
2.7 Comments
2.8 That's it
3.1 User defined procedures
3.2 The if command
4.1 Tcl list
4.2 The foreach command
4.3 The lrange command
4.4 The lappend command
4.5 The lset command
4.6 The lsort command
4.7 List values against variable names
5.1 The append command
5.2 The string command
5.3 string range
5.4 string index
5.5 string equal
5.6 string compare
5.7 string match
5.8 string map
5.9 string is
5.10 More string subcommands
5.11 Advanced string matching
6.1 Converting strings to lists
6.2 From strings to list of chars
6.3 Converting lists to strings
6.4 Manipulating strings as lists
7.1 Local variables
7.2 Top level
7.3 Global variables
7.4 Procedures arguments and pass by value
7.5 Procedures with a variable number of arguments
7.6 Procedures with default arguments
7.7 Recursion
7.8 Recursion limit
8.1 The switch command
8.2 The for command
8.3 break and continue
8.4 The lack of goto
9.1 Programs executing programs: the eval command
9.2 Breaking the rules with uplevel
9.3 Passing variable names to procedures
9.4 Mapping scripts to lists
9.5 The rename command
9.6 Expanding lists into arguments in Tcl 8.5
Additional 20 chapters in the printed version.
Related man pages
Links
Author HomeTclers Wiki |
Copyright © 2004 Salvatore Sanfilippo. All rights reserved. This online book is for personal use only. It cannot be copied to other web sites or further distributed in any form. |