Looping Constructs in Tcl
Tcl provides three core looping commands: while, for, and foreach. while {condition} {body} repeats the body as long as the braced condition evaluates true, re-checking it before each iteration. for {init} {test} {next} {body} takes four separate brace-delimited arguments, an initialization script, a test expression, a per-iteration update script, and the loop body, executed in that order each pass, closely mirroring C's for loop but with every clause as its own Tcl script rather than baked-in syntax. foreach varname list body is the idiomatic way to walk over a Tcl list without manual indexing.
Cricket analogy: Net practice sessions use different loop styles: a bowler doing 'while there's daylight, keep bowling' is a while loop, a fixed 'bowl exactly 6 overs' drill is a for loop, and 'go through each fielder in the slip cordon and check their position' is a foreach loop over a list of fielders.
The while and for Loops
The for loop's four arguments are all ordinary Tcl scripts evaluated at specific points: for {set i 0} {$i < 10} {incr i} {puts $i} initializes i once, tests $i < 10 before every iteration, runs incr i after every iteration, and runs the body in between. Because test is evaluated by expr internally, it must be a valid boolean expression each time, and because next runs after the body, a break inside the body will skip the final increment for that pass. A while loop is simpler and better suited when there's no natural counter, such as reading input until end-of-file: while {[gets $chan line] >= 0} {...}.
Cricket analogy: The four-part structure of for {set i 0} {$i < 10} {incr i} {...} is like an over: init zeroes the over counter, test checks 'is the innings still under 10 overs', next increments the count after each over, and the body is the actual bowling -- each part runs at its own moment.
The foreach Command
foreach x {a b c} {puts $x} assigns each list element to x in turn and runs the body once per element. foreach also supports iterating multiple lists in parallel by supplying several varname/list pairs, e.g. foreach {name score} {Alice 90 Bob 85} {...} walks the flat list two elements at a time, and foreach a $list1 b $list2 {...} walks two separate lists side by side, padding the shorter one with empty strings if their lengths differ.
Cricket analogy: foreach {name score} {Kohli 82 Rohit 45 Bumrah 3} {...} walking a flat list two at a time mirrors reading a scorecard row by row, pulling a batter's name and their score together in each pass rather than as two separate lists.
break, continue, and Loop Control
break immediately exits the innermost enclosing loop, skipping any remaining iterations, while continue skips straight to the next iteration's test/update step without running the rest of the current body. Both work identically inside while, for, and foreach. A subtle bug beginners hit is writing for {set i 0} {$i < 10} {} {...} and forgetting to increment i anywhere in the body -- since the next script is empty, the loop runs forever unless something inside the body itself updates i or calls break.
Cricket analogy: A captain calling for a bowling change mid-over is like break, exiting the current spell immediately regardless of how many balls were planned; skipping a wide ball without counting it toward the over is like continue, moving straight to the next delivery.
# Sum numbers 1 through 10 using for
set total 0
for {set i 1} {$i <= 10} {incr i} {
set total [expr {$total + $i}]
}
puts "Sum: $total"
# Iterate a list with foreach, skip and break
foreach fruit {apple banana cherry durian elderberry} {
if {$fruit eq "durian"} {
continue
}
if {$fruit eq "elderberry"} {
break
}
puts "Fruit: $fruit"
}foreach can walk multiple lists at once: foreach a $list1 b $list2 {...} binds a and b from two separate lists in lockstep, padding the shorter list with empty strings if the lists differ in length. This is often cleaner than manually indexing with lindex inside a for loop.
for {set i 0} {$i < 10} {} {body} with an empty next clause will loop forever unless the body itself updates i or calls break -- Tcl does not automatically increment anything for you. Also remember the test clause must be inside braces ({$i < 10}, not $i < 10) so it's re-evaluated fresh on every pass instead of being computed once at parse time.
while {cond} {body}repeats while its braced condition is true, re-testing before every iteration.for {init} {test} {next} {body}takes four separate script arguments run at four distinct points in each pass.foreach varname list {body}is the idiomatic way to walk a Tcl list without manual indexing.foreachcan bind multiple variables per list, or walk several lists in parallel with multiple varname/list pairs.breakexits the innermost loop immediately;continueskips to the next iteration's test/update step.- Leaving the for loop's next clause empty is legal but risks an infinite loop if nothing in the body updates the loop variable.
- Keep loop test expressions inside braces so expr re-evaluates variables fresh each iteration instead of once at substitution time.
Practice what you learned
1. Which Tcl loop command is best suited for reading lines from a file until end-of-file, when the number of lines is unknown in advance?
2. What do the four brace-delimited arguments to for represent, in order?
3. What happens when continue is executed inside a for loop's body?
4. Given foreach {a b} {1 2 3 4 5 6} {puts "$a-$b"}, how many times does the body run and what are the pairs?
Was this page helpful?
You May Also Like
Conditionals in Tcl
Learn how Tcl evaluates branching logic with if/elseif/else, the expr command, comparison operators, and the switch command for multi-way branching.
Procedures in Tcl
Learn how to define reusable commands with proc, including default arguments, variable-arity args, return values, scope, and recursion.
Arrays and Dictionaries in Tcl
Understand Tcl's associative arrays and the modern dict command, and learn when to reach for each key-value structure.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics