if 0 {Richard Suchenwirth 2004-01-25 - For counted loops, Tcl has inherited the for command from C with its lengthy syntax. Python on the other hand provides only a list iterator like Tcl's foreach, and offers an integer range constructor range() to iterate over counted loops:
range(1,5) -> [1, 2, 3, 4] range(4) -> [0, 1, 2, 3]
(A similar thing was the index vector generator, iota, in APL). You can also specify the step-width, which might also be negative. This construct comes handy in Tcl too, where we can then choose between
for {set i 0} {$i < 5} {incr i} {...} foreach i [.. 0 5] {...}
I chose the fancy name ".." as suggestive for a range. Here's the code:}
proc .. {a {b ""} {step 1}} { if {$b eq ""} {set b $a; set a 0} ;# argument shift if {![string is int $a] || ![string is int $b]} { scan $a %c a; scan $b %c b incr b $step ;# let character ranges include the last set mode %c } else {set mode %d} set ss [sgn $step] if {[sgn [expr {$b - $a}]] == $ss} { set res [format $mode $a] while {[sgn [expr {$b-$step-$a}]] == $ss} { lappend res [format $mode [incr a $step]] } set res } ;# one-armed if: else return empty list } proc sgn x {expr {$x>0? 1: $x<0? -1: 0}}
if 0 {For testing this, I came up with a cute and tiny asserter/tester routine:}
proc must {cmd result} { if {[set r [uplevel 1 $cmd]] != $result} { error "$cmd -> $r, expected $result" } }
#-- Tests pass silently, but raise an error if expectations are not met:
must {.. 5} {0 1 2 3 4} must {.. 0 10 3} {0 3 6 9} must {.. -10 -100 -30} {-10 -40 -70} must {.. 2 -2 -1} {2 1 0 -1} must {.. 0 0} {} must {.. A D} {A B C D} must {.. z a -1} {z y x w v u t s r q p o n m l k j i h g f e d c b a}
KPV It would be useful if this function also had the ability to generate alphabet ranges, e.g [.. A D] => {A B C D}. Perl has this capability and it's surprisingly useful. - RS: Your wish is my command :) It didn't take much to change, considering that characters are integers. For convenience I allowed (as your example suggests) that character ranges run up to the last specified character (while for integers, they run until just below the end limit...)