[Python-ideas] Cofunctions - Getting away from the iterator protocol

Ron Adam ron3200 at gmail.com
Sun Nov 6 08:20:31 CET 2011


On Sun, 2011-11-06 at 13:09 +1300, Greg Ewing wrote:
> Ron Adam wrote:
> > On Thu, 2011-11-03 at 14:47 +1300, Greg Ewing wrote:
> > 
> >>However, if something other than 'yield' is used for coroutine
> >>suspension -- such as a 'coyield' keyword or coyield() function --
> >>then I think this problem becomes solvable. In a cogenerator
> >>(i.e. a generator running in coroutine mode), 'coyield' would
> >>do what 'yield' does in normal mode (simply suspend the frame),
> >>and 'yield(value)' would raise StopIteration(value).
> > 
> > Well it sounds reasonable,  but how would that actually work?  What if
> > the coroutine is paused at coyield, and you need to do a next rather
> > than a conext?
> 
> That situation shouldn't occur, because if a generator is
> suspended at a coyield, it's already in the middle of one
> next() call, and you shouldn't be trying to start another
> one until the first one is finished.

Yes, I figured that out just a little before you posted this.

A coyield suspends it in between normal yield statements, and you dont
want to steel the value from the the next next(), .send(), or .throw()
call.  Which is why those won't work to continue as well.

What is needed is a different path out (and back) to the coroutine that
doesn't interfere with the standard yield behavior.  Or as you describe
it here.

> Yes, I'm leaning back towards a completely separate protocol
> now. We seem to need a number of new protocol features in
> any case, and allowing the two protocols to overlap is just
> creating needless confusion, I think.

I think adding a .resume() method to all generators would be good.  That
keeps it simple.  It would just raise an exception in the case of a
non-suspended generator.  Which may be useful in a loop as well.

Looking at ceval.c, I think Nick's suggestion of adding a new
WHY_SUSPEND would be good.  And along with it, a TARGET(GEN_SUSPEND)
block that sets up a SuspendIteration exception, and returns WHY_SUSPEND
to the generator object.

At that point it could save anything it needs before raising the
exception, and when the resume method is called, restore what it needs
before calling the frame evel loop.

I still haven't quite worked out how to get back to the original
next(), .send() or .throw() call.

Cheers,
   Ron


> > And that is the whole problem... trying to make this all un_coconfusing
> > to the average python programmer.  If it's coconfusing to us, they don't
> > have a chance.  ;-)
> 







More information about the Python-ideas mailing list