# Done by Reinhard Max
# at the Texas Tcl Shoot-Out 2000
# in Austin, Texas.
proc do {script arg2 {arg3 {}}} {
#
# Implements a "do <script> until <expression>" loop
# The "until" keyword ist optional
#
# It is as fast as builtin "while" command for loops with
# more than just a few iterations.
#
if {[string compare $arg3 {}]} {
if {[string compare $arg2 until]} {
return -code 1 "Error: do script ?until? expression"
}
} else {
# copy the expression to arg3, if only
# two arguments are supplied
set arg3 $arg2
}
set ret [catch { uplevel $script } result]
switch $ret {
0 -
4 {}
3 {return}
default {
return -code $ret $result
}
}
set ret [catch {uplevel [list while "!($arg3)" $script]} result]
return -code $ret $result
}You can alter this from do-until to do-while by changing the uplevel'ed while to not !().I'll leave the analysis up to the reader, because this is an excellent example of control construct creation.DGP: An update of this proc for Tcl 8.5 (TIP 90) would be a good idea. If no one else does it, I'll get to it eventually.RS: If you change the proc line to
proc do {script {arg2 {}} {arg3 {}}} {
if {![string length $arg2$arg3]} {set arg2 0}you win the added functionality of calling do $body which works like the not too unfrequent while 1 $body. Switching between while and until can of course also be built in... if {[string compare $arg3 {}]} {
switch -- $arg2 {
until {set bool "!"}
while {set bool ""}
default {return -code 1 "usage: do script ??until|while? expr?"}
}
}
...
set ret [catch {uplevel [list while ${bool}($arg3) $script]} result]rmax: This "do while|until" loop is now a part of tcllib's control package.
