shy stackless Re: ANNOUNCE: xsdb -- the eXtremely Simple Database goes alpha
Jp Calderone
exarkun at intarweb.us
Thu Dec 11 09:26:07 EST 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