www.gibmonks.com

  Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 6.  Control Structure Commands


Foreach

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 were introduced in Tcl 7.5. The syntax for the simple case of a single variable and a single list is:

foreach loopVar valueList commandBody

The first argument is the name of a variable, and the command body is executed once for each element in the list with the loop variable taking on successive values in the list. The list can be entered explicitly, as in the next example:

Example 6-8 Looping with foreach.
set i 1
foreach value {1 3 5 7 11 13 17 19 23} {
   set i [expr $i*$value]
}
set i
=> 111546435

It is also common to use a list-valued variable or command result instead of a static list value. The next example loops through command-line arguments. The variable argv is set by the Tcl interpreter to be a list of the command-line arguments given when the interpreter was started:

Example 6-9 Parsing command-line arguments.
# argv is set by the Tcl shells
# possible flags are:
# -max integer
# -force
# -verbose
set state flag
set force 0
set verbose 0
set max 10
foreach arg $argv {
   switch -- $state {
      flag {
         switch -glob -- $arg {
            -f*    {set force 1}
            -v*    {set verbose 1}
            -max   {set state max}
            default {error "unknown flag $arg"}
         }
      }
      max {
         set max $arg
         set state flag
      }
   }
}

The loop uses the state variable to keep track of what is expected next, which in this example is either a flag or the integer value for -max. The -- flag to switch is required in this example because the switch command complains about a bad flag if the pattern begins with a - character. The -glob option lets the user abbreviate the -force and -verbose options.

graphics/tip_icon.gif

If the list of values is to contain variable values or command results, then the list command should be used to form the list. Avoid double quotes because if any values or command results contain spaces or braces, the list structure will be reparsed, which can lead to errors or unexpected results.

Example 6-10 Using list with foreach.
foreach x [list $a $b [foo]] {
   puts stdout "x = $x"
}

The loop variable x will take on the value of a, the value of b, and the result of the foo command, regardless of any special characters or whitespace in those values.

Multiple Loop Variables

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.

Example 6-11 Multiple loop variables with foreach.
foreach {key value} {orange 55 blue 72 red 24 green} {
   puts "$key: $value"
}
orange: 55
blue: 72
red: 24
green:

If you have a command that returns a short list of values, then you can abuse the foreach command to assign the results of the commands to several variables all at once. For example, suppose the command MinMax returns two values as a list: the minimum and maximum values. Here is one way to get the values:

set result [MinMax $list]
set min [lindex $result 0]
set max [lindex $result 1]

The foreach command lets us do this much more compactly:

foreach {min max}[MinMax $list] {break}

The break in the body of the foreach loop guards against the case where the command returns more values than we expected. This trick is encapsulated into the lassign procedure in Example 10-4 on page 131.

Multiple Value Lists

The foreach command has the ability to loop over multiple value lists in parallel. In this case, each value list can also have one or more variables. The foreach command keeps iterating until all values are used from all value lists. If a value list runs out of values before the last iteration of the loop, its corresponding loop variables just get the empty string for their value.

Example 6-12 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

      Previous section   Next section
    Top