[Keith Vetter] 2003-09-29 -- I love tcl's [foreach] command. It's a beautiful command that lets you express elegantly some otherwise cumbersome constructs. Compared to similar constructs in other languages, tcl's foreach command outshines them all. People often complain that tcl's ''simple'' syntax can be annoying--it's prolix and confusing to the initiate: when is a comment a comment? (even [JO] got that one wrong), always having to use [expr] to do any math, the whole {expand} debate [http://mini.net/tcl/9468], etc. But the foreach command is one of tcl's strengths. Most of the common uses of foreach such as walking a list, swapping two variables foreach {a b} [list $b $a] break , handling multiple return values from a function (see [foreach] for more details) have similar constructs in other languages, often times more elegantly expressed. But once you get past these simple uses of foreach, other languages can't compare. Take even the simple example of traipsing down a list--in tcl you can take bigger steps. Try doing this in perl (without destroying the data list): foreach {x y} $dataSet { ... } Another simple (but I admit dubious) use of foreach is setting multiple variables at once: foreach x [$w canvasx $x] y [$w canvasy $y] break But advanced use of foreach that many people don't realize comes when you traipse over a list of variable '''names'''. Below is an example from I program I wrote that cleans up user supplied data: foreach var {north south east west altitude} { set $var [::Data::Fix [set $var]] } Here's a more complicated example: # Get canvas dimensions shrunk by some amount foreach who {x0 y0 x1 y1} val [.c cget -scrollregion] d {30 20 -30 -20} { set $who [expr {$val + $d}] } Now that I've admitted my love of the foreach command, I confess I have two complaints. First, I'd love some kind of iteration counter. But the obvious way of doing that is via a special variable and that not the ''tcl way''. Second, I'd love foreach to understand [streams], but that's a whole other discussion. ''Could iteration be done with an extra var running over a generated list of ints? -[jcw]'' [KPV] -- definitely yes, especially if that list of ints were a stream. But the problem is knowing when to stop. The best I could come up with is below, but sometimes $myList is a function return value and then this doesn't work as well: foreach var $myList cnt [range 0 [llength $myList]] {...} [RS] does integer iteration like this, admittedly not very tricky: set i -1 foreach element $list { incr i ;# safer here than in the end, because the loop might be left early w. continue # do something with $element and $i here } [glennj]: or even fall back to the venerable [for] command for {set i 0} {$i < [llength $myList]} {incr i} { set element [lindex $myList $i] # do something with $element and $i here } [KPV]: yes, but by using [for] you loose all the special features of [foreach] like grabbing multiple elements or traipsing multiple lists. [DKF]: The point when you need [for] is when you need to stride over list elements by variable amounts (e.g. when parsing getargs()-style arguments). At that point, you've no real choice.