I'm playing with the idea of iterators and generators from Python.
Basically, an iterator is an object that supports a single operation,
next, which produces the iterator's next value. Iterators can be
created from sequences in the obvious way by iterating through the
items.

Python also supports generators, which are a limited form of coroutine:

def gen():
    yield 1
    yield 2
    yield 3

defines a generator function which, when called, returns an iterator
which produces the values from each yield statement in turn.

There are two questions which come to mind while trying to design these:

1. What's the most idiomatic way in Factor to implement next? In
Python, it returns a new value each time it's called, and signals that
it has run out of values by raising a special StopIteration exception.
This has the major advantage that iterators don't have to generate a
value until it's needed - there's no empty? function which needs to
know whether next will work the next time you call it - just call it
and catch the exception. Is using an exception for control flow like
this a reasonable option in Factor? An alternative would be to return
an extra flag - but I suspect that will make stack handling a lot more
messy.

2. The obvious way of implementing generators in Factor would be on
top of continuations/coroutines. But one of the reasons Python's
generators are limited is that they can be efficient (full coroutines
are a lot more costly than generators). Which makes me wonder whether
continuations might be expensive in Factor.

Consider the following 2 implementations of an iterator over a sequence:

First, using a tuple class

    TUPLE: seqiter seq pos ;
    M: sequence iter 0 seqiter boa ;
    M: seqiter next [ [ seq>> ] [ pos>> ] bi nth ] [ [ 1 + ]
change-pos drop ] bi

Second, using coroutines

    : iter ( seq -- iter ) '[ _ [ coyield* ] map ] cocreate ;
    : next ( iter -- elt ) *coresume ;

The first is clearly specific to sequences, and while it's not
complex, having to manage the position variable manually is mildly
fiddly. On the other hand, it's pretty easy to see how the coroutine
version works if you know how map works, and generalising to any
function that spits out values one after another is pretty obvious.

So I guess the question is, are continuations/coroutines costly enough
to make them a bad choice for something like this? I know this is
premature optimisation, but I'm curious nevertheless...

Any other comments on this idea would be gratefully accepted, as well.

Paul.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Factor-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/factor-talk

Reply via email to