[Python-ideas] Implementing Coroutines (was Cofunctions - Back to Basics)

Mark Shannon mark at hotpy.org
Fri Oct 28 11:33:36 CEST 2011


Hi,

Full coroutines have a number of advantages over the proposed 
cofunctions. For one, coroutines require *no* language changes.

Here is a simple coroutine class interface (feel free to substitute/add 
your own names/signatures).

class Coroutine:

    def __init__(self, callable):
       ...

    def resume(value):
       '''Passes value to coroutine, either as initial parameter to 

          callable or as return value of yield'''

    def co_yield(value):
        'Yields (returns) value back to caller of resume() method.'

    def stop():
        'Stops the coroutine'

In order to implement this, it must be possible to transfer control 
*sideways* from one frame to another, without unwinding either stack.
In order to do this, Python-to-Python calls within the interpreter must 
not make calls at the C (OS/hardware) level.

This is quite simple to implement in practice.
Currently CPython does something like this (for Python to Python calls).

In interpreter:
     call PyFunction.__call__(parameters)

In PyFunction.__call__():
     Create new frame with parameters.
     Call interpreter with new frame.

By changing the call sequence to something like:

In interpreter:
     frame = PyFunction.make_frame(parameters)
     Push frame to frame-stack
     jump to start of new function.	

we have a 'stackless' implementation which can support coroutines.

The implementation of Coroutines in a portable fashion is explained on 
pages 7 and 8 of this paper:
http://www.lua.org/doc/jucs05.pdf

(Sorry to keep quoting Lua papers, but it is a cleaner VM than CPython. 
Python is a better language, though :) )

Stackless uses a slightly different approach, not for any fundamental 
reason, but because their goal is to minimise the diff with CPython.

Adding coroutines may create problems for the other implementations.
PyPy already has a stackless implementation, but Jython and IronPython 
might find to it harder to implement.
Any Jython or IronPython folks care to comment?

In summary, the cofunction proposal is a work-around for a limitation in 
the VM. By fixing the VM we can have proper coroutines.
Surely, it is better to make the VM support the features we want/need 
rather than bend those features to fit the VM?

Cheers,
Mark.



More information about the Python-ideas mailing list