[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: * Sequences of natural numbers are often useful in programming, so the command is of very general use. * It may become idiomatic to write: foreach x [[range 0 10]] instead of for {set x 0} {$x < 10} {incr x} for small loops. It's much clear. * The Python semantic appears to be the best for languages where indexes are zero-based (Pascal noted it, and I think it's a smart observation). * If implemented in a smart way, [range] may speed-up Tcl loops compared to [for]. A smart implementation should cache small ranges and return the shared object for the next call. * At some point Tcl may include TIP 192 in order to make ranges used for loops to have a space complexity of O(1). I'm ready to implement and TIP-fy it, but it's probably best to "sense" the Tclers ideas before to go forward. So, comments are very welcomed. ---- [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 } ---- [LV] When this topic first arose some time ago, the [Python] function was described to me as one in which the numbers were only generated as needed. That way, if one specified a range of a million, one got them, but didn't wait around for them or carry the penalty of the long list. That delayed generation of value functionality, generalized beyond integers, seems like something more useful for Tcl. It might be used for floats, alphas, etc. [CL] notes that Python has both range() and xrange(); only the latter is lazy. [SS]: TIP 192 (lazy lists) covers exactly this aspect. ---- See also [Integer range generator]. ---- [Category Algorithm]