'''[http://www.tcl.tk/man/tcl/TclCmd/for.htm%|%for]''', a [Tcl Commands%|%built-in] [Tcl] command, provides an iterative loop construct. ** See Also ** [break]: [continue]: [expr]: [foreach]: [if]: [while]: [fold] / [map] / [zip] etc: [for in%|%for ... in]: ** Synopsis ** '''for''' ''start test next body'' ** Documentation ** [http://www.tcl.tk/man/tcl/TclCmd/for.htm%|%official reference]: ** Description ** '''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 [[`[expr]`] argument. [[`for`] first invokes the Tcl interpreter to execute ''start''. Then it iteratively evaluates ''test'' as an expression, and if the result is non-zero, then evaluates ''body'' as a Tcl script. Finally, it evaluates ''next'' as a Tcl script, and then repeats the loop. `[continue]` and `[break]` function in a manner similar to the corresponding [[`for`] terminates when ''test'' evaluates to `0`. If a [[`[continue]`] is invoked within ''body'' then any remaining commands in the current evalutaion of ''body'' are skipped, ''next'' is evaluated as a Tcl script, ''test'' is again evaluated, and so on. If [[`[break]`] is invoked within ''body'' or ''next'', [[`for`] returns immediately. [[`[break]`] and [[`[continue]`] function in a manner similar to the corresponding statements in C. [[`for`] returns an empty string. `for` returns an empty string. ''test'' should almost always be enclosed in braces. If not, variable substitutions will be made by Tcl before it calls [[`for`], causing [[`for`] to see the value intead of the variable, and preventing it from detecting changes made to the variable in ''body''. This is likely to result in an infinite loop, and to the possibility of unintended effects from [double substitution]. If ''test'' is enclosed in braces, Tcl does not perform substitutions on it and therefore does not step on the toes of [[`if`] as it uses [[`[expr]`] to perfrom its own substitutions. 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" } ====== See also: [TclHelp] ** `for` vs `[foreach]` ** ** [[`[for]`] vs [[`[foreach]`] ** `[foreach]` is generally better style for non-numeric looping. Those [[`[foreach]`] is generally better style for non-numeric looping. Those because they think of an indexed array where a Tcl programmer writes: ====== 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 [[`[foreach]`] with a fixed list is more convenient than [[`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 Some find the idea of using [[`[foreach]`] on a range of integers so nice that they pour some sugar over [[`for`]: ====== proc range {from to: to} { set res [list] 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 [[`[for]`]. ---- The main difference between `for` and `[foreach]` when iterating over a 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 ====== 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 when written as the following `[foreach]`: is actually faster when written as the following [[`[foreach]`]: ====== set index -1 foreach item $list { incr index 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. ---- [AMG]: Sometimes I need to chew through a list and conditionally edit, replace, 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 One option: ====== set list {0 1 2 3 4 5 6} set index -1 foreach elem $list { incr index if {$elem % 2 == 0} { lset list $index [expr {-$elem}] } } ====== Another option: ====== 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}] } } ====== Which is preferred? Here's another option. ====== 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. :^) [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 that my code was just an unrolled version of your [[`[lcomp]`]. The last three 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 ====== 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 another idea: ''dictionary comprehensions!'') [NEM] 2006-06-12: List comprehensions can be generalised to allow queries over a range of different data structures. At the end of this road are things like [http://www-db.in.tum.de/~grust/files/monad-comprehensions.pdf%|%monad comprehensions (Torsten Grust)] and Microsoft's new [LINQ] framework for [.NET]. ---- [Sarnold] finds this quick enough : ====== 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 [RS]: [[`[lmap]`] is a lambda/map compromise pretty much in Tcl's [[`[foreach]`] spirit. ---- [wdb]: In [Python] there is only a `[foreach]` equivalent, and for-loops are [wdb]: In [Python] there is only a [[`[foreach]`] equivalent, and for-loops are 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! ** `for` vs `[while]` ** ** [[`for`] vs [[`[while]`] ** 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. 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 graph_component {graph v} { 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. The corresponding loop with `[while]` is less clear: 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 [[`[foreach]`] alone wouldn't work, because the ''queue'' can grow. A [[`[while]`]–[[`[foreach]`] 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] } ====== ** Dynamic Expressions ** The bracing of ''test'' minimizes interpretation of the value by Tcl, before passing the value to `[expr]`. Tcl interpretation can be used, though to passing the value to [[`[expr]`]. Tcl interpretation can be used, though to accomplish that is to call '''[expr]''' from within the expression itself: ====== 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. ** Making Use of all the Arguments to `for` ** ** Making Use of all the Arguments to [[`for`] ** [lexfiend] 2006-06-12: While most people think of `for` in terms of C-style [lexfiend] 2006-Jun-12: While most people think of [for] in terms of C-style [https://groups.google.com/d/msg/comp.lang.tcl/GHxR1W_p7-Y/s1Q_h2BzDUwJ%|%how to gets with an arbitrary "newline" character], [comp.lang.tcl], 2006-06-11, that ''start'', ''test'' and ''next'' could do many other things too. The code fragment in question: ====== for {fconfigure $pipe -eofchar \u0000} { [string length [set record [read $pipe]]] } {seek $pipe 1 current} { # process $record here } ====== is an impressively succinct rendition of the more typical: ====== fconfigure $pipe -eofchar \u0000 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 } ====== Of course, the downside to using this sort of reductionist construct is that it 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 ====== 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 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. 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]`] ** 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: ====== 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 While ====== expr $i < $size ====== would raise an error ====== expr {$i<$size} ====== , as well as the use within the `for` only returns a 1, causing the loop to run 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 A quick way to [assert] that a value is an integer is to [incr] it by 0, like ====== set size [getresult from operation] incr size 0 for {set i 0} {$i<$size} {incr i} { set workingarray($i) 0 } ====== <> Arts and Crafts of Tcl-Tk Programming | Tcl syntax help | Command | Control Structure