% source serial.tcl
% serial create s
% foreach fruit {apples oranges pears banannas} {
> puts [format {%03d %s} $s $fruit]
>}
001 apples
002 oranges
003 pears
004 banannasAnyway, I'm so impressed by my own cleverness, that I need to post it online immediately. (It needs SubCommands and named arguments to work...#serial.tcl
#Copyright April 13, 2005 - Pierre Coueffin
source subcommands.tcl
proc serial {command args} {
subcommand $command args {
create {var {start 1} {step 1}} {
incr start [expr -1 * $step]
upvar $var v
if {[regexp {read {serial trace (-?[0-9]+)}} \
[trace info variable v]]} {
error "The variable $var has already been declared serial."
}
set v $start
trace add variable v read [list serial trace $step]
}
array {var vals {step 1}} {
upvar $var v
foreach {idx val} $vals {
set v($idx) [expr $val - $step]
}
trace add variable v read [list serial trace $step]
}
trace {step var idx _op} {
upvar $var v
if {$idx == {}} {
incr v $step
} else {
incr v($idx) $step
}
}
forget {var} {
upvar $var v
trace remove variable v read \
[list serial trace [serial stepsize v]]
}
stepsize {var {newstep {}}} {
upvar $var v
if {[llength $newstep] > 0} {
serial forget v
serial create v $v $newstep
return $v
} else {
regexp {read {serial trace (-?[0-9]+)}} \
[trace info variable v] match step
return $step
}
}
last {var} {
upvar $var v
return [incr v [expr -1 * [serial stepsize v]]]
}
default {} {
error "serial: I don't know how to \"$command\"!"
}
}
}SS With Jim Closures it's as simple as:
proc make-counter {} {lambda {} {{i 0}} {incr i}}
set s [make-counter]
foreach fruit {apples oranges pears banannas} {
puts [format {%s %s} [$s] $fruit]
}output:1 apples 2 oranges 3 pears 4 banannas
[Pierre Coueffin]:Wow, you're fast! I had a few other samples to post, but you managed to slip the edit in while I was checking that the last one worked... I'll just tuck them away here:
% puts $s 5 % puts $s 6 % serial last s 7 % serial last s 7 % serial stepsize s 1 % serial stepsize s 10 7 % puts $s 17 % set s 5 5 % puts $s 15 % puts $s 25 % puts $s 35Or how about an array of them?
% serial array sa {0 0 1 5 bob 3} 2
% puts $sa(0)
0
% puts $sa(0)
2
% puts $sa(0)
4
%
% puts $sa(bob)
3
% puts $sa(bob)
5
% puts $sa(bob)
7escargo 2005-04-13: This very much like Icon generators, which produce a new value when they are invoked. (Icon generators cannot have their current value and step size increased like these can.)
RS has this variation:
set s 0
trace var s r {incr s ;#}
foreach fruit {apples oranges pears bananas} {
puts [format {%s %s} $s $fruit]
}which shows1 apples 2 oranges 3 pears 4 banannas
rdt Wow, leave it to RS to come up with a simple, easy to use solution. Thanks.

