Version 0 of Integer range generator

Updated 2004-01-25 20:13:38

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
    set ss [sgn $step]
    if {[sgn [expr {$b - $a}]] == $ss} {
        set res $a
        while {[sgn [expr {$b-$step-$a}]] == $ss} {
            lappend res [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} {}

Arts and crafts of Tcl-Tk programming