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

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


On Thu, Dec 11, 2003 at 02:03:35PM +0000, Duncan Booth wrote:
> aaron at reportlab.com (Aaron Watters) wrote in
> news:9a6d7d9d.0312110538.568014ef at posting.google.com: 
> 
> > regarding the use of stackless in
> > http://xsdb.sourceforge.net
> > "Fredrik Lundh" <fredrik at pythonware.com> wrote in message
> > news:<mailman.56.1071124178.9307.python-list at python.org>... 
> >> 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 stackless.channel 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:
            try:
                e = gstack[-1].next()
            except StopIteration:
                gstack.pop()
            else:
                if isinstance(e, types.GeneratorType):
                    gstack.append(e)
                else:
                    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.

    Jp





More information about the Python-list mailing list