seq is a command line interface program that is very popular in Unix/Linux. I find myself using it often in my Tcl code so I wrote my own seq.
[LES] 2025-01-05: added atwo new blocks (the first ones) to get rid of the "08" octal interpretation. I doubt the octal interpretation will ever be useful in the context of seq. Note that Tcl 9 no longer does the octal assumption.
======
proc p.seq {args} { # remove unwanted zeros
set cleanargs {}
for {set x 0} {$x < [llength $args]} {incr x} {
if {[string length [lindex $args $x]] > 1} {
set newitem [string trimleft [lindex $args $x] 0]
lappend cleanargs $newitem
} else {lappend cleanargs [lindex $args $x]}
}
set args $cleanargs
# the same again, but with negative integers
set cleanargs {}
for {set x 0} {$x < [llength $args]} {incr x} {
if {[string range [lindex $args $x] 0 0] == "-"} {
set newitem [string trimleft [string range [lindex $args $x] 1 end] 0]
lappend cleanargs "-$newitem"
} else {lappend cleanargs [lindex $args $x]}
}
set args $cleanargs
if {[llength $args] > 3 || [llength $args] < 1} {return ""}
set mode ""
set intcount 0
for {set x 0} {$x < [llength $args]} {incr x} {
if {[string is integer [lindex $args $x]]} {incr intcount}
}
if {$intcount == [llength $args]} {set mode "integer"}
set alphacount 0
for {set x 0} {$x < [llength $args]} {incr x} {
if {[string length [lindex $args $x]] > 1} {continue}
if {[string is alpha [lindex $args $x]]} {incr alphacount}
}
if {$alphacount == [llength $args]} {set mode "alpha"}
if {$mode == ""} {return ""}
# INT MODE
if {$mode == "integer"} {
lassign $args A B C
if {[llength $args] == 3 && $B < 1} {return ""}
if {[llength $args] == 3 && $A < $C} {
for {set i $A} {$i <= $C} {set i [expr {$i + $B}]} {lappend _output $i}
return $_output
}
if {[llength $args] == 3 && $A > $C} {
for {set i $A} {$i >= $C} {set i [expr {$i - $B}]} {lappend _output $i}
return $_output
}
if {[llength $args] == 1} {
set A 1; set B [lindex $args 0]
if {$B <= 1} {return $args}
for {set i $A} {$i <= $B} {incr i} {lappend _output $i}
return $_output
}
if {$A == $B} {return $A}
if {$A < $B} {
for {set i $A} {$i <= $B} {incr i} {lappend _output $i}
return $_output
}
if {$A > $B} {
for {set i $A} {$i >= $B} {incr i -1} {lappend _output $i}
return $_output
}
}
# ALPHA MODE
if {$mode == "alpha"} {
if {[llength $args] < 1 || [llength $args] > 2} {return ""}
if {[llength $args] == 1} {
if {[string is lower $args]} {
set args "a $args"
} else {set args "A $args"}
}
lassign $args A B
if {$A == $B} {return $A}
set An [scan $A %c]; set Bn [scan $B %c]
set _output {}
foreach i [p.seq $An $Bn] {
if {[string is alpha [format %c $i]] == 1} {lappend _output [format %c $i]}
}
return $_output
}
}
======
Testing it:
======
> p.seq 4
1 2 3 4
> p.seq 4 11
4 5 6 7 8 9 10 11
> p.seq 11 4
11 10 9 8 7 6 5 4
> p.seq 4 -4
4 3 2 1 0 -1 -2 -3 -4
> p.seq 3 3 18
3 6 9 12 15 18
> p.seq 3 2 18
3 5 7 9 11 13 15 17
> p.seq a g
a b c d e f g
> p.seq A G
A B C D E F G
> p.seq A g
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g
> p.seq g A
g f e d c b a 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
======