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 }
I think the Tcl core should include the range command as proposed in my reference implementation (that's semantically equivalent to Python's) for the following reasons:
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