Version 42 of for

Updated 2012-11-30 16:10:36 by pooryorick

Summary

for - "For" loop

for start test next body

official reference

man page

For is a looping command, similar in structure to the C for statement. The start, next, and body arguments are scripts statement. The start, next, and body arguments must be Tcl command strings, and test is an expression string. The for command first invokes the Tcl interpreter to execute start. Then it repeatedly evaluates test as an expression; if the result is non-zero it invokes the Tcl interpreter on body, then invokes the Tcl interpreter on next, then repeats the loop. The command terminates when test evaluates to 0. If a continue command is invoked within body then any remaining commands in the current execution of body are skipped; processing continues by invoking the Tcl interpreter on next, then evaluating test, and so on. If a break command is invoked within body or next, then the for command will return immediately. The operation of break and continue are similar to the corresponding statements in C. For returns an empty string. for returns an empty string. Note: test should almost always be enclosed in braces. If not, variable substitutions will be made before the for command starts executing, which means that variable changes made by the loop body will not be considered in the expression. This is likely to result in an infinite loop. If test is enclosed in braces, variable substitutions are delayed until the expression is evaluated (before each loop iteration), so changes in the variables will be visible. For an example, try the following script with and without the braces around $x<10: test should almost always be enclosed in braces. Otherwise, substitutions for {set x 0} {$x<10} {incr x} {

    puts "x is $x"

}

(From: [TclHelp])
See also: [TclHelp]
** See Also **

   * [break]
   * [continue]
   * [expr]
   * [foreach]
   * [if]
   * [while]
   * [fold] / [map] / [zip] etc
   * [for in%|%for ... in]

** [For] vs [Foreach] **
** `for` vs `[foreach]` **
'''[Foreach]''' is generally better style in non-numeric looping. Those
accustomed to writing in C sometimes find this a difficult habit to learn,
because they think of an indexed array where a Tcl coder writes simply
`[foreach]` is generally better style for non-numeric looping. Those
set color_list "red blue umber mauve"
foreach color $color_list {...}

In some situations, using foreach with a fixed list is more convenient In some situations, using a foreach with a fixed list is more convenient than a for, even if the list is numeric. Compare:

foreach i {1 2 3 4 5} {...
for {set i 1} {$i <= 5} {incr i} {...

Some find the idea of using foreach on a range of integers so nice that they wrap an actual for for sugaring: proc range {from to: to} { proc range {from "to:" to} {

    for {set i $from} {$i<=$to} {incr i} {lappend res $i}
    set res

} foreach i range 1 .. 5 {...

This is, however, slower than `for`.
This is, however, slower than the '''for'''.
----

The main difference between [for] and [foreach] when iterating over a list is
that with [for] the index into the list is available, whereas with [foreach] it
is not.  [foreach] can however be preferable even if the list index is needed.
What would traditionally be coded as
The main difference between `for` and `[foreach]` when iterating over a
for {set index 0} {$index < [llength $list]} {incr index} {
    set item [lindex $list $index]
    # Now do something using both $index and $item
    ...
}

is actually faster as the following foreach: set index -1 set index -1; foreach item $list {incr index

    ...

}

In order for `[continue]` to do the right thing, `[incr] index` comes first in
The reason to [incr] ''index'' first in the loop body is that this makes
[continue] do the right thing.
---- 

or remove elements.  I can easily read "copies" of each element in the list
using `[foreach]`, but when the condition triggers I need the list index
using [['''foreach''']], but when the condition triggers I need the list index
for [[[lreplace]]], [[[lset]]], [[[linsert]]], and the like.  What's the best
way to handle this?  Option the first:
One option:
set list {0 1 2 3 4 5 6}
set index -1
set index 0
    incr index
        lset list $index [expr {-$elem}]
    }
}
    incr index

Option the second: set list {0 1 2 3 4 5 6} for {set index 0} {$index < llength $list} {incr index} {

    set elem [lindex $list $index]
    if {$elem % 2 == 0} {
        lset list $index [expr {-$elem}]
    }

}


set list {0 1 2 3 4 5 6}
set result [list]
foreach elem $list {
    if {$elem % 2 == 0} {
        lappend result [expr {-$elem}]
    } else {
        lappend result $elem
    }
}
set list $result

Better still would be a list comprehension (e.g., lcomp), but to me it Better still would be a list comprehension (e.g., [lcomp]), but to me it

Lars H: Good question; I often find myself wondering the same thing. I suspect that rebuilding the list is on the whole the best approach, when possible (I think dragging the index around is sometimes unavoidable). An nice thing about the rebuild method is that it allows for more functional ways of writing the body; in this case the extreme is probably

set list {0 1 2 3 4 5 6}
set result [list]
foreach elem $list {
    lappend result [expr {
        $elem % 2 == 0 ? -$elem : $elem
    }]
}
set list $result

AMG: If your code is functional, does that mean mine is dysfunctional? :^) Seriously, we should look into list comprehensions a bit more. Just how much do they cost, when implemented in Tcl or C? Can something be done in C to allow for a better Tcl implementation? How do list comprehensions compare to writing the equivalent for/foreach commands? Which is more readable writing the equivalent [for]s/[foreach]es? Which is more readable

With lcomp, the above is written: With [lcomp], the above is written: set list lcomp {[expr {$x * -1 ** (1 - $x % 2)}} x {0 1 2 3 4 5 6}]

Yeah, maybe that exponentiation is going overboard, but I couldn't help myself. :^)
Yeah, maybe that exponentiation is going overboard, but I couldn't help myself.
''[Lars H]: If you rewrite that expression using the ?: operation, you'll see
that my code was just an unrolled version of your [lcomp]. The last three
functional style.
functional style.''
`[lcomp]` can be modified to `[eval]` its first argument, perhaps in a
[[[lcomp]]] can be modified to [[[eval]]] its first argument, perhaps in a
child interpreter with an [['''emit''']] command.  That would allow the above
to be written in a hybrid functional-imperative notation:

set list [lcomp {

    if {$x % 2 == 0} {
        emit [expr {-$x}]
    } else {
        emit $x
    }

} x {0 1 2 3 4 5 6}]

Plus, if '''`emit`''' can take multiple arguments and/or can be called
Plus, if [['''emit''']] can take multiple arguments and/or can be called
number (including zero) of output elements.  Hmm.

Hey, joyous idea.  The first argument gets passed unmodified to `[eval]`
Hey, joyous idea.  The first argument gets passed unmodified to [[[eval]]] (or
[[[interp eval]]]), which should (??) allow Tcl to bytecode compile it.  Bonus!
But the nests of [[[foreach]]]es would still be pieced together every time
[[[lcomp]]] is called, so don't put [[[lcomp]]] in a loop.
(This is topical because it's an attempt to find alternatives to `for` for
(This is topical because it's an attempt to find alternatives to [['''for''']]
for list processing.  But we might want to move to another page before long.
Hey, another idea: ''dictionary comprehensions!'')
[NEM] 2006-06-12: List comprehensions can be generalised to allow queries over
[NEM] ''12 June 2006'': List comprehensions can be generalised to allow queries
over a range of different data structures. At the end of this road are things
like ''monad comprehensions''
[http://www.inf.uni-konstanz.de/~grust/files/thesis-GI.pdf], and Microsoft's
new [LINQ] framework for .NET.
----


proc map {cmd mylist} {
    set r ""
    foreach e $mylist {lappend r [$cmd $e]}
    set r
}
proc negate-even {x} {expr {$x%2==0 ? -$x : $x}}
map negate-even {0 1 2 3 4 5 6}

With lambda, it could be even simpler. With lambda, it could be even simpler. - RS: lmap is a lambda/map compromise pretty much in Tcl's foreach spirit. RS: lmap is a lambda/map compromise pretty much in Tcl's


for vs while

wdb: In Python there is only a foreach equivalent, and for-loops are In some languages, the range of a for loop is determined at the start of the loop, and unbounded loops must rather be coded using while. Tcl is not one of those languages (because of C heritage), so for is preferable to while whenever there is a loop variable. In Tcl, you can define a proc range as follows: One case where this happens is a loop over the elements of a list (queue), where processing one element may cause further elements to be appended to the list: proc range {from {to ""} {step 1}} {

    set queue [list $v]
    for {set n 0} {$n < [llength $queue]} {incr n} {
        set v [lindex $queue $n]
        if {[info exists seen($v)]} then {continue}
        set seen($v) {}
        lappend queue {*}[dict get $graph $v]
    }
    return [array names seen]

}

(''[graph]'' here is assumed to be a dictionary mapping vertices to their lists
of neighbours. ''v'' is the vertex whose component one wishes to compute.)
''[graph]'' here is assumed to be a dictionary mapping vertices to their lists
The corresponding loop with [while] is less clear:
proc graph_component {graph v} {
    set queue [list $v]
    set n 0
    while {$n < [llength $queue]} {
        set v [lindex $queue $n]
        incr n
        if {[info exists seen($v)]} then {continue}
        set seen($v) {}
        lappend queue {*}[dict get $graph $v]
    }
    return [array names seen]
}

foreach alone wouldn't work, because the queue can grow. A whileforeach combination is possible, but less clear than the simple for: proc graph_component {graph v} {

    set queue [list $v]
    while {[llength $queue]} {
        set next {}
        foreach v $queue {
            if {[info exists seen($v)]} then {continue}
            set seen($v) {}
            lappend next {*}[dict get $graph $v]
        }
        set queue $next
    }
    return [array names seen]

}


<<discussion>>

''[lexfiend] 2006-Jun-12'' - While most people think of [for] in terms of C-style integer iteration or list-walking, [DKF] provides a neat reminder in [http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/187c51d56fe9efe6/4c0d7360873f54b3?tvc=1#4c0d7360873f54b3] that ''start'', ''test'' and ''next'' could do many other things too.  The code fragment in question:
set op <
    [string length [set record [read $pipe]]]
} {seek $pipe 1 current} {
    # process $record here
}

fconfigure $pipe -eofchar \u0000 while 1 { while {1} { # Read up to the next eof char, as configured

 set record [read $pipe]

if {string length $record} {

    # process $record here

} else {

    break
# skip over the eof char
seek $pipe 1 current
}

can sometimes be hard to be sure your logic is correct. 8-)

[RS]: The flexibility of the three first arguments to for was directly
inherited from [C], where you have the same liberties.

[Lars H]: Actually, Tcl gives you ''greater'' liberties than C here, because in
C the ''start'' and ''next'' are restricted to being expressions, and
expressions in C cannot do any flow control.  In a C expression, there's no way, for example, to `[return]` or even throw an `[error]`, whereas Tcl lets you do
expressions in C cannot do any flow control — there's no way to e.g. [return]
or even throw an [error] from within a C expression — whereas Tcl lets you do

[aspect]: While the `for` code above suffers in readability, it's heading
[aspect]: While the [for] code above suffers in readability, it's heading down
a useful path. [Lisp]ers would tend to look for an underlying abstraction which
is easy in tcl:
proc with-records {eofchar $_record body} {
    upvar 1 $_record record
    set _eofchar [fconfigure $pipe -eofchar]
    for {fconfigure $pipe -eofchar $eofchar} {
        [string length [set record [read $pipe]]]
    } {seek $pipe 1 current} {
        uplevel 1 $body
    }
    fconfigure $pipe -eofchar $_eofchar
}

In writing this construct, the need to reset -eofchar at the end of the look In writing this construct, the need to reset eofchar at the end of the look was exposed and easily addressed. Also I'd tend to use the default name $_ for the record instead of having to explicitly provide it, but that's a matter of taste. As is the name of the procedure, which I'm not entirely happy with. But the point is that making New Control Structures is easy: you don't have to be shoehorn your problem into for, foreach and while like in most other languages.

Tips and tricks on for

Tips and Tricks on for

A poster to comp.lang.tcl mentioned the following problem. Some code was set up like this: A poster to comp.lang.tcl mentioned the following problem. Some code was set set size getresult from operation for {set i 0} {$i<$size} {incr i} {

    set workingarray($i) 0

}

However, due to a mistake, the output from `getresult` changed at one point
However, due to a mistake, the output from getresult changed at one point from
being a number to being a string.  Rather than causing for to raise an error,
the bug caused the for loop to loop thousands of time, until in the poster's
case, memory was used up.
While 

expr $i < $size

expr {$i<$size}

as well as the use within the for only returns a 1, causing the loop to run forever.
, as well as the use within the `for` only returns a 1, causing the loop to run
Test your variables to ensure they actually have the type of value you expect, after getting values from a user or external source.
A quick way to [assert] that a value is an integer is to [incr] it by 0, like so: 
set size [getresult from operation]
incr size 0
for {set i 0} {$i<$size} {incr i} {
    set workingarray($i) 0
}


The bracing of test will result in expr parsing the contents. But in braced expressions, expr does not tolerate operators to be passed in as variables. If you want to do that, call an explicit expr without braced condition (but inside brackets and braces, as explained above), so the Tcl parser substitutes that in each loop repetition:

set op "<"
for {set x 0} {[expr $x $op 10]} {incr x} {puts "x is $x"} ;#RS

Note that not bracing the expr expression will mean there are two substitution rounds. This can lead to problems if some substituted value is not a simple number.

Alternatively, use quotes and backslashes:

set op "<"
for {set x 0} "\$x $op 10" {incr x} {puts "x is $x"}

This substitutes op before calling for, but x only when the expression is evaluated. This technique makes it easier to handle complex substituted values, but the need to escape all $ signs can be a burden in complex expressions.


wdb In Python there is only a foreach equivalent, and for-loops are done with ranges such as 4..11.

In Tcl, you can define a proc range as follows:

proc range {from {to ""} {step 1}} {
    if {$to eq ""} then {
        set to $from
        set from 0
    }
    set result {}
    for {set x $from} {$x < $to} {set x [expr {$x + $step}]} {
        lappend result $x
    }
    set result
}

Now, having this function, you can say:

foreach i [range 4 11] {puts $i}

which makes your code shorter (but not faster).

Lars H: And places you at the mercy of the endpoint conventions used — which are not the same in this range as in the other range on this page. Murphy strikes again!