You are here: Surpac Concepts > Macros > TCL > TCL control flow
GEOVIA Surpac

TCL Control Flow

In all but the simplest scripts, some mechanism is needed to control the flow of execution. Tcl offers decision-making constructs (if-else and switch statements) as well as looping constructs (while, for, and foreach statements), both of which can alter the flow of execution in response to some condition. The following examples serve to illustrate these constructs.

Example 4.1:

    set my_planet "earth"
    if {$my_planet == "earth"} {
        puts "I feel right at home."
    } elseif {$my_planet == "venus"} {
        puts "This is not my home."
    } else {
        puts "I am neither from Earth, nor from Venus."
    }
    set temp 95
    if {$temp < 80} {
        puts "It's a little chilly."
    } else {
        puts "Warm enough for me."
    }
      

Output:

I feel right at home.

Warm enough for me.

Example 4.1 makes two uses of the if-statement. It sets the value of the variable "my_planet" to "earth", and then uses an if-statement to choose which statement to print. The general syntax of the if-statement is as follows:

if test1 body1 ?elseif test2 body2 elseif ...? ?else bodyn?

If the test1 expression evaluates to a true value, then body1 is executed. If not, then if there are any elseif clauses present, their test expressions are evaluated and, if true, their bodies are executed. If any one of the tests is made successfully, after its corresponding body is executed, the if-statement terminates, and does not make any further comparisons. If there is an else clause present, its body is executed if no other test succeeds.

Another decision-making construct is the switch-statement. It is a simplification of the if-statement that is useful when one needs to take one of several actions depending on the value of a variable whose possible values are known. This is illustrated in Example 4.2, which uses a switch statement to print a sentence, depending on the value of a variable "num_legs".

Example 4.2:

    set num_legs 4
    switch $num_legs {
         2 {puts "It could be a human."}
         4 {puts "It could be a cow."}
         6 {puts "It could be an ant."}
         8 {puts "It could be a spider."}
         default {puts "It could be anything."}
    }           
      

Output:

It could be a cow.

The switch-statement has two general forms (both of which are described in detail in the manual page), but the form used here is as follows:

switch ?options? string {pattern body ?pattern body ...?}

Basically, the string argument is compared to each of the patterns and if a comparison succeeds, the corresponding body is executed, after which the switch statement returns. The pattern "default", if present, is always matched, and thus its body always executed if none of the earlier comparisons succeed.

It is often useful to execute parts of a program repeatedly, until some condition is met. In order to facilitate this, Tcl offers three looping constructs: the while, for, and foreach statements, each of which is shown in the examples below.

Example 4.3:

for {set i 0} {$i < 10} {incr i 1} {
    puts "In the for loop, and i == $i"
}
      

Output:

In the for loop, and i == 0

In the for loop, and i == 1

In the for loop, and i == 2

In the for loop, and i == 3

In the for loop, and i == 4

In the for loop, and i == 5

In the for loop, and i == 6

In the for loop, and i == 7

In the for loop, and i == 8

In the for loop, and i == 9

The general syntax for the for-loop is as follows:

for init test reinit body

The init argument is a Tcl script that initializes a looping variable. In the for-loop used in Example 4.3, the looping variable was called "i", and the init argument simply set it to 0. The test argument is a Tcl script which will be evaluated to decide whether or not to enter the body of the for-loop. Each time this script evaluates to a true value, the body of the loop is executed. The first time this script evaluates to false, the loop terminates. The reinit argument specifies a script that will be called after each time the body is executed. In Example 4.3, the reinit script increments the value of the looping variable, "i". Thus, for-loop in this example executes its body 10 times, before its test script evaluates to false, causing the loop to terminate.

Example 4.4:

set i 0
while {$i < 10} {
    puts "In the while loop, and i == $i"
    incr i 1
}
      

Output:

In the while loop, and i == 0

In the while loop, and i == 1

In the while loop, and i == 2

In the while loop, and i == 3

In the while loop, and i == 4

In the while loop, and i == 5

In the while loop, and i == 6

In the while loop, and i == 7

In the while loop, and i == 8

In the while loop, and i == 9

Example 4.4 illustrates the use of a while-loop, the general syntax of which follows the form:

while test body

The basic concept behind the while-loop is that while the script specified by the test argument evaluates to a true value, the script specified by the body argument is executed. The while loop in Example 4.4 accomplishes the same effect as the for-loop in Example 4.3. A looping variable, "i", is again initialized to 0 and incremented each time the loop is executed. The loop terminates when the value of "i" reaches 10.

Note, that in the case of the while-loop, the initialization and re-initialization of the looping variable are not part of the while-statement itself. Therefore, the initialization of the variable is done before the while-loop, and the re-initialization is incorporated into its body. If these statements were left out, the code would probably still run, but with unexpected results.

Example 4.5:

foreach vowel {a e i o u} {
    puts "$vowel is a vowel"
}
      

Output:

a is a vowel

e is a vowel

i is a vowel

o is a vowel

u is a vowel

The foreach-loop, illustrated in Example 4.5, operates in a slightly different manner to the other types of Tcl loops described in this section. Whereas for-loops and while-loops execute while a particular condition is true, the foreach-loop executes once for each element of a fixed list. The general syntax for the foreach-loop is:

foreach varName list body

The variable specified by varName takes on each of the values in the list in turn, and the body script is executed each time. In Example 4.5, the variable "vowel" takes on each of the values in the list "{a e i o u}" (Tcl list structure will be discussed in more detail in a later section), and for each value, the body of the loop is executed, resulting in one printed statement each time.