Posted to tcl by dbohdan at Sat Sep 05 12:40:57 GMT 2015view pretty

# http://wiki.tcl.tk/13840

# This works...

set countRef [ref 0 int]

proc make-counters n {
    global countRef
    set result {}
    for {set i 0} {$i < $n} {incr i} {
        lappend result [lambda {} countRef {
            setref $countRef [+ [getref $countRef] 1]
        }]
    }
    return $result
}

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}

# ...but will continue to count from the same point since the counter is
# global.

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}


unset f
unset g
unset countRef
puts ----------------

# This also does.

proc make-counters n [list [list countRef [ref 0 int]]] {
    set result {}
    for {set i 0} {$i < $n} {incr i} {
        lappend result [lambda {} countRef {
            setref $countRef [+ [getref $countRef] 1]
        }]
    }
    return $result
}

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}


unset f
unset g
puts ----------------

# As does this.

proc make-counters n {
    set countRef [ref 0 int]
    set result {}
    for {set i 0} {$i < $n} {incr i} {
        lappend result [lambda {} countRef {
            setref $countRef [+ [getref $countRef] 1]
        }]
    }
    return $result
}

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}

lassign [make-counters 2] f g
foreach p {f f f g g f} {
    puts "$p [[set $p]]"
}


unset f
unset g

# Output:
# f 1
# f 2
# f 3
# g 4
# g 5
# f 6
# f 7
# f 8
# f 9
# g 10
# g 11
# f 12
# ----------------
# f 1
# f 2
# f 3
# g 4
# g 5
# f 6
# f 7
# f 8
# f 9
# g 10
# g 11
# f 12
# ----------------
# f 1
# f 2
# f 3
# g 4
# g 5
# f 6
# f 1
# f 2
# f 3
# g 4
# g 5
# f 6