shy stackless Re: ANNOUNCE: xsdb -- the eXtremely Simple Database goes alpha

Jp Calderone exarkun at
Thu Dec 11 15:26:07 CET 2003

On Thu, Dec 11, 2003 at 02:03:35PM +0000, Duncan Booth wrote:
> aaron at (Aaron Watters) wrote in
> news:9a6d7d9d.0312110538.568014ef at 
> > regarding the use of stackless in
> >
> > "Fredrik Lundh" <fredrik at> wrote in message
> > news:<mailman.56.1071124178.9307.python-list at>... 
> >> Aaron Watters wrote:
> >> > 5) use an event loop and use a generator for the relevant code;
> >> when you discover that you need to pause, yield to the framework.
> > 
> > Please tell me I'm missing something, but I don't think
> > this will really help.  The problem is that I need to "yield"
> > or "suspend" or "send something across a channel" from about
> > 45 places in the code some of which are arbitrarily deep into
> > multiple recursions.  The generator thing will only allow
> > me to go one level deep into a single call -- no?  By contrast
> > the mechanism is a far more general construct,
> > allowing me to "yield" at any point without restructuring the
> > code at all.  Stackless rules.
> The generator solution may not be appropriate for your task, but it isn't 
> entirely accurate to say that you can only go one level deep. You can (sort 
> of) yield from arbitrarily deep function nesting, or even from recursive 
> functions. The catch though is that you do have to write the code in a 
> slightly contorted manner in order to yield from below the first function.
> The rule to follow is simply: any function which wants to yield, or which 
> calls a function that wants to yield has to be a generator and has to be 
> called from a 'for' loop which itself yields.
> e.g. A generator that walks a tree recursively:
>          def inorder(t):
>              if t:
>                  for x in inorder(t.left):
>                      yield x
>                  yield t.label
>                  for x in inorder(t.right):
>                      yield x

  This works, but it is even easier.  All you need is top-level code to
handle it:

    def unroll(f, *a, **kw):
        gstack = [iter(f(*a, **kw))]
        while gstack:
                e = gstack[-1].next()
            except StopIteration:
                if isinstance(e, types.GeneratorType):
                    yield e

    def inorder(t):
        if t:
            yield inorder(t.left)
            yield t.label
            yield inorder(t.right)

    unroll(inorder, t)

    A bit more frameworky code, but it's all isolated in one place, which is
much nicer than having to spread it all over the place.


More information about the Python-list mailing list