Version 11 of Iterator Protocol

Updated 2014-02-13 02:20:52 by pooryorick

Iterator Protocol is a description of one method for implementing iterators in Tcl.

Description

A common iterator protocol is presented. This particularly useful with coroutines, but could be used with any procedure. The protocol is simple: An iterator is a command which one calls repeatedly until the command no longer exists. The last value returned by the command before it ceases to exist should not be considered one of the iterated values, as the iterator command has no way of knowing whether it is finished or not until the last time it is called, and must therefore return one time after there are no more valid values to return. for ... in ... is a drop-in replacement for [for] that supports this protocol and provides an expanded syntax for looping over iterators.

This example implements the iterator protocol:

proc iterproc {} {
    while {some condition} {
        return [something useful]
    }
    rename iterproc {}
    return
}

while 1  {
    set val [iterproc]
    if {[namespace which [namespace current]::iterproc] eq {}} {
        break
    }
    do stuff with $val
}

For a coroutine, a little more plumbing is usually added:

proc iterproc {} {
    #the first yield returns an out-of-band value to give the caller a chance
    #to settle the name of the proc
    yield [info level 0]
    while {some condition} {
        yield [something useful]
    }
    return
}

iterproc myiterator
while 1  {
    set val [myiterator]
    if {[namespace which [namespace current]::iterproc] eq {}} {
        break
    }
    do stuff with $val
}

Making the last value a signal rather than a valid value is similar to the protocol for file operations, where an empty string signals some file condition, and [eof] provides more detail about that condition. Without this mechanism, an iterator would have to pre-compute the next value and be prepared to return it at the next invocation, which defeats the desirable feature of lazy computation, where the iterator doesn't compute the next value until asked for it.