[Python-ideas] Cofunctions - Back to Basics

Greg Ewing greg.ewing at canterbury.ac.nz
Thu Oct 27 09:44:45 CEST 2011


Nick Coghlan wrote:
> Could you add a pseudocode expansion, similar to
> the one in PEP 343?
> 
> Something like:
> 
>     _make_call = True
>     _cocall = getattr(obj, "__cocall__", None)
>     if _cocall is not None:
>         _cocall_result = _cocall(*args, **kwds)
>         _make_call = _cocall_result is NotImplemented
>     if _make_call:
>         _result = obj(*args, **kwds)
>     else:
>         _result = _cocall_result

It's not quite as simple as that, because whether a cocall was
done determines whether the return value is subjected do a
yield-from or used directly as the result.

This could be expressed by saying that

    result = obj(*args, **kwds)

expands into

    _done = False
    _cocall = getattr(obj, "__cocall__", None)
    if _cocall is not None:
       _iter = _cocall(*args, **kwds)
       if _iter is not NotImplemented:
          result = yield from _iter
          _done = True
    if not _done:
       result = obj.__call__(*args, **kwds)

> Perhaps the PEP needs a "with not codef:" construct to revert to
> normal calling semantics for a section of code within a coroutine? You
> could still explicitly yield from such a code block, but it would
> otherwise be the coroutine equivalent of a critical section.

This is perhaps worth thinking about, but I'm not sure it's
worth introducing special syntax for it. If you're working from
the mindset of making as few assumptions as possible about
suspension points, then your critical sections should be small
and confined to the implementations of a few operations on
your shared data structures. Now if you have a class such as

    class Queue:

       def add_item(self, x):
          ...

       def remove_item():
          ...

then it's already obvious from the fact that these methods
are defined with 'def' and not 'codef' that they can't cause
a suspension, either directly or indirectly, and will therefore
be executed atomically from the coroutine perspective.

In other words, wherever you might feel inclined to enclose
a set of statements in a 'with not codef' block, you can get
the same effect by factoring them out into an ordinary function,
the atomicity of which is easy to verify by inspecting the
function header. So the motivation for introducing more special
syntax here appears weak.

-- 
Greg



More information about the Python-ideas mailing list