[Python-Dev] Simple coroutines?

Clark C. Evans cce at clarkevans.com
Tue Aug 24 21:12:08 CEST 2004


On Tue, Aug 24, 2004 at 07:45:13AM -0400, Daniel Bickett wrote:
| Tell me if I'm missing something here, but with the exception of your
| two introductory keywords (a subject I thought was supposed to be
| sacred, with the intention of keeping the amount of keywords as small
| as possible,) how much difference is there to generators? Are you
| saying the run() method, after having been called initially, will
| return a value indicative of the cooperator's business when called
| again?

In that such a 'cooperator' would keep its state on the heap (in an
iterator object to be more precice), it is very much like a generator.
In fact, one could implement it using a SuspendIteration exception,
in addition to a StopIteration.  SuspendIteration would signal that
the caller of the iterator _may_ call next() again.  In other words,
it says: 

  "I didn't produce a value this time, but call me again, and
   I may have a value for you".

Specializations of SuspendIteration could signal that the process
is blocked on a socket read, or some other low-level process.  So
that the caller (which would be a generic run-loop in most cases)
would only attempt next() once the block is resolved.

| It seems like a similar feat could be achieved with custom generators
| and boolean yield statements.

  I currently do this in twisted.flow, however, it requires that
  intermediate generators "check" for the special value.   This
  intermediate work is slow (since it is not in C) and tedious
  since it is mostly boilerplate catch-check-yield kinda stuff

On Tue, Aug 24, 2004 at 02:58:42PM +0100, Moore, Paul wrote:
| From: Greg Ewing
| > There will be a new statement:
| >
| >     suspend
| >
| [...]
| >
| >    do another_coop()
| >
| > would be equivalent to
| >
| >    co = another_coop()
| >    while co.run():
| >        suspend
| 
| 
| I'm not sure I see the difference between suspend/do and
| yield True/for _ in co: pass, other than possibly that
| co-operators and generators are intended to be mixed (which
| strikes me as implausible).

You'd definately want to mix them.  For example, a 'cooperator'
would be reading from a socket, it could do one of three things:

  yield the next line from the sender
  raise StopIteration if the socket closed
  raise SuspendIteration if the read() is blocked

The 'suspend' statement is analogous to raising SuspendIteration.

| I'm likely to be missing something here, but I don't follow
| the semantics you are suggesting.
| 
| If there was a simple, realistic use case for this, it might
| help clarify the semantics. (For extra credit, mix co-operators
| and generators in your use case so that the semantics of
| interaction are shown as well :-))

There ya go. ;)

Clark


More information about the Python-Dev mailing list