[Python-ideas] Cofunctions: It's alive! Its alive!
greg.ewing at canterbury.ac.nz
Wed Aug 11 02:49:19 CEST 2010
Guido van Rossum wrote:
> I'm convinced of the utility. I still find the mechanism somehow odd
> or clumsy; the need for two new keywords (codef and cocall), a new
> builtin (costart), and a new api (__cocall__) doesn't sit well.
The costart function isn't strictly necessary, because you can
always invoke __cocall__ directly. It's just there for
convenience and for symmetry with all the other function/typeslot
It's possible that 'codef' could be eliminated by following a
similar rule to generators, i.e. if it contains 'codef' anywhere
then it's a cofunction. But then we're back to the situation
of having to insert a dummy statement to force cofunctionness
some of the time. I expect this be needed much more frequently
with cofunctions than with generators, because it's very rare
that you call a generator for a side effect, whereas with
coroutines it's quite normal.
I also feel strongly that it would be too implicit. We
manage to get away with it in generators because from the
outside a generator is just a normal function that happens to
return an iterator. But a cofunction has a very different
interface, and the caller must be aware of that, so I would
much rather make it explicit at the point of definition.
A decorator could be provided to take care of the no-cocall
case, but since it wouldn't be required in most cases, and
people wouldn't bother to use it when they didn't need to,
so it wouldn't serve to make the interface explicit in
Maybe something could be done to force the decorator to be
used on all cofunctions, such as making them neither callable
nor cocallable until the decorator has been applied, but
things are getting terribly convoluted by then. There would
be something perverse about a definition that looks to all
the world like a plain function, except that you can't actually
do anything with it until it's been wrapped in a specific
> - Is it possible to mix and match yield, yield from, and cocall in the
> same function? Should / shouldn't it be?
Yes, it is. A cofunction is a kind of generator, and 'yield'
and 'yield from' work just the same way in a cofunction as
they do in an ordinary generator.
> (This new keyword in particular chafes me, since we've been
> so successful at overloading 'def' for so many meanings -- functions,
> methods, class methods, static methods, properties...)
I understand how you feel, but this case seems fundamentally
different to me. All of those decorators are pretty much
agnostic about what they wrap -- they just take a callable
object and externally modify its behaviour. A decorator with
the same properties as codef would need to be much more
intimately connected with the thing it's wrapping.
> - If we had cocall, would yield from still be useful?
You need *some* way to suspend a cofunction, so if not
yield, some other keyword would need to be invented. There
doesn't seem to be any point to that.
If you're asking whether it needs to be able to send and
receive values when used in a cofunction, I suppose it's
not strictly necessary, but again there doesn't seem to be
any point in disallowing these things.
> - The syntax worries me. Your PEP suggests that cocall binds tightly
> to an atom. That would mean that if the cofunction is really a
> comethod, you'd have to parenthesis it,
No, if you examine the grammar in the PEP you'll see that
the atom can be followed by a subset of the trailers allowed
after atoms in other contexts, so it's possible to write
x = cocall foo.blarg.stuff(y)
which parses as
x = cocall (foo.blarg.stuff)(y)
> Also things lke 'cocall foo' (no call syntax) weird me
That's a syntax error -- a cocall *must* ultimately
terminate with an argument list.
> - How much of the improved error flagging of codef/cocall can be
> obtained by judicious use of decorators and helper functions? (I need
> this in Python 2.5 *now*. :-)
I'll have to think about that and get back to you.
More information about the Python-ideas