Version 6 of range

Updated 2004-04-29 10:57:38

SS: Python's alike range. The semantic should be exactly the same (and seems the more sensible for Tcl also).

Examples:

 range 10                    ;# => 0 1 2 3 4 5 6 7 8 9
 range 10 20                 ;# => 10 11 12 13 14 15 16 17 18 19
 range 10 20 2               ;# => 10 12 14 16 18
 range 20 10 -2              ;# => 20 18 16 14 12

Code:

 # range ?start? end ?step?
 #
 # Python's alike range function.
 # Returns the [start,end) integer range.
 #
 # Example:
 #
 # foreach x [range 0 10] y [range 20 0 -2] {
 #     puts "$x $y"
 # }
 proc range args {
     set l [llength $args]
     if {$l == 1} {
         set start 0
         set step 1
         set end [lindex $args 0]
     } elseif {$l == 2} {
         set step 1
         foreach {start end} $args break
     } elseif {$l == 3} {
         foreach {start end step} $args break
     } else {
         error {wrong # of args: should be "range ?start? end ?step?"}
     }
     set result {}
     if {$start <= $end} {
         for {set j $start} {$j < $end} {incr j $step} {
             lappend result $j
         }
     } else {
         for {set j $start} {$j > $end} {incr j $step} {
             lappend result $j
         }
     }
     return $result
 }

RS: Here's a minimal variant that only does step-width 1:

 proc range {from to} {
    if {$to>$from} {concat [range $from [incr to -1]] $to}
 }
 % range 0 5
 0 1 2 3 4
 % range 1 6
 1 2 3 4 5

DKF: Extending is easy.

  proc range {from to {step 1}} {
     if {$to>$from} {concat $from [range [incr from $step] $to $step]}
  }

however this is inefficient. Better to do this:

  proc range {from to {step 1}} {
     set res $from; while {$to>$from} {lappend res [incr from $step]}; return $res
  }

or even this, adapting to work with negative steps...

  proc range {from to {step 1}} {
     set res $from
     while {$step>0?$to>$from:$to<$from} {lappend res [incr from $step]}
     return $res
  }

See also Integer range generator


Category Algorithm