[Python-ideas] Cofunctions - Getting away from the iterator protocol
Nick Coghlan
ncoghlan at gmail.com
Tue Nov 8 06:46:31 CET 2011
On Tue, Nov 8, 2011 at 3:30 PM, Ron Adam <ron3200 at gmail.com> wrote:
> Generator API.
>
> Outside generator <--> Inside generator
>
> next() yield
> .send()
> .throw()
>
>
> Inverted generator API
>
> Outside cothread <--> Inside cothread
>
> .resume() suspend()
> throw()
>
> Where resume works like yield, (yield to cothread), and suspend() works
> like .send(). Throw() raises an exception at the resume() call,
> like .throw() raises an exception at the yield in a generator.
No, that doesn't make any sense. When the coroutine throws an
exception internally it's done - we don't *want* to preserve the stack
any more, because something broke and we won't be resuming it.
Instead, we let the exception bubble up the stack and if nothing
handles it, we pass it back to the thread that called resume().
The reason we need an explicit throw() is that the data request (or
whatever it was we suspended to wait for) might fail - in that case,
the thread calling resume() needs to be able to indicate this to the
cothread by resuming with an exception.
The flow control parallels are like this:
Inside the generator/cothread:
yield -> cothread.suspend() # Wait to be resumed
return -> return # Finish normally
raise -> raise # Bail out with an error
Outside the generator/cothread
send() -> resume() # Resume execution normally (optionally providing data)
throw() -> throw() # Resume execution with an exception
Don't worry about next() in this context, since it's just an alternate
spelling for send(None).
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list