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.
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. ;-)