• Musings about the tcllib generator package

    From Julian H J Loaring@21:1/5 to All on Tue Mar 29 05:21:34 2022
    I am trying to get my head around the Tcllib generator package (version 0.2). It took a while for the penny to drop that generators seem to me to be a bit quantum in that they are changed by observing/accessing them...

    In the following snippets, the "foreach" is the one provided by the generator package not the Tcl ::foreach command. Once a foreach loop over a generator, xs, completes, the generator is exhausted so "generator length $xs" will be 0.

    ~~~~~~~~~~~~~~~~~~~~
    1)
    In the following interactive session, I notice that "generator head ..." returns a generator, but the value of this generator is empty:

    ===
    % package require generator
    0.2
    % generator define range {n m} {
    for {set i $n} {$i <= $m} {incr i} {
    generator yield $i
    }
    }
    ::range
    % set r [range 21 30]
    ::generator::generator1
    % set h [generator head $r]
    ::generator::generator2
    % puts "<[$h]>"

    ===

    In the underlying definition of the "generator take ..." subcommand:

    proc head xs { take 1 $xs }
    define take {n xs} {
    finally destroy $xs
    foreach x $xs {
    if {[incr i] >= $n} { break }
    yield $x
    }
    }

    I think the inequality test should be >, because, as is, the loop will exit early if n = 1:

    define take {n xs} {
    finally destroy $xs
    foreach x $xs {
    if {[incr i] > $n} { break }
    yield $x
    }
    }

    2) Conceptually, should "generator head ..." return a generator (like it currently does) or should it return a value?

    The latter would require:

    proc head xs { takeList 1 $xs }

    3) The "generator last ..." returns nothing:
    ===
    % set l [generator last $r]
    % puts "<$l>"

    ===

    "generator last ..." is defined as follows:

    proc last xs {
    foreach x $xs { }
    return $x
    }

    In the above definition, running this loop will exhaust the generator, xs, so the returned x is empty.

    So, conceptually, I think "generator last ..." should return a value because every item of the generator must be yielded in order to produce the last
    value, exhausting the generator in the process.

    Here is a modified version of "generator last ..." which returns the last value of the range:

    proc last xs {
    set l ""
    foreach x $xs { set l $x }
    return $l
    }

    ~~~~~~~~~~~~~~~~~~~~
    Any comments? I am slowly feeling my way with Functional Programming ideas such as generators, so let me know if I have missed the point!

    kind regards
    Julian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)