[Python-checkins] r83942 - peps/trunk/pep-3152.txt

brett.cannon python-checkins at python.org
Wed Aug 11 02:25:27 CEST 2010


Author: brett.cannon
Date: Wed Aug 11 02:25:26 2010
New Revision: 83942

Log:
Add PEP 3152: Cofunctions, by Greg Ewing.


Added:
   peps/trunk/pep-3152.txt   (contents, props changed)

Added: peps/trunk/pep-3152.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-3152.txt	Wed Aug 11 02:25:26 2010
@@ -0,0 +1,165 @@
+PEP: 3152
+Title: Cofunctions
+Version: $Revision$
+Last-Modified: $Date$
+Author: Gregory Ewing <greg.ewing at canterbury.ac.nz>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 13-Feb-2009
+Python-Version: 3.3
+Post-History:
+
+
+Abstract
+========
+
+A syntax is proposed for defining and calling a special type of generator
+called a 'cofunction'.  It is designed to provide a streamlined way of
+writing generator-based coroutines, and allow the early detection of
+certain kinds of error that are easily made when writing such code, which
+otherwise tend to cause hard-to-diagnose symptoms.
+
+This proposal builds on the 'yield from' mechanism described in PEP 380,
+and describes some of the semantics of cofunctions in terms of it. However,
+it would be possible to define and implement cofunctions independently of
+PEP 380 if so desired.
+
+
+Specification
+=============
+
+Cofunction definitions
+----------------------
+
+A new keyword ``codef`` is introduced which is used in place of ``def`` to
+define a cofunction. A cofunction is a special kind of generator having the
+following characteristics:
+
+1. A cofunction is always a generator, even if it does not contain any 
+   ``yield`` or ``yield from`` expressions.
+
+2. A cofunction cannot be called the same way as an ordinary function. An
+   exception is raised if an ordinary call to a cofunction is attempted.
+
+Cocalls
+-------
+
+Calls from one cofunction to another are made by marking the call with
+a new keyword ``cocall``. The expression
+
+::
+
+    cocall f(*args, **kwds)
+
+is semantically equivalent to
+
+::
+
+    yield from f.__cocall__(*args, **kwds)
+
+except that the object returned by __cocall__ is expected to be an
+iterator, so the step of calling iter() on it is skipped.
+
+The full syntax of a cocall expression is described by the following
+grammar lines:
+
+::
+
+    atom: cocall | <existing alternatives for atom>
+    cocall: 'cocall' atom cotrailer* '(' [arglist] ')'
+    cotrailer: '[' subscriptlist ']' | '.' NAME
+
+The ``cocall`` keyword is syntactically valid only inside a cofunction.
+A SyntaxError will result if it is used in any other context.
+
+Objects which implement __cocall__ are expected to return an object
+obeying the iterator protocol. Cofunctions respond to __cocall__ the
+same way as ordinary generator functions respond to __call__, i.e. by
+returning a generator-iterator.
+
+Certain objects that wrap other callable objects, notably bound methods,
+will be given __cocall__ implementations that delegate to the underlying
+object.
+
+New builtins, attributes and C API functions
+--------------------------------------------
+
+To facilitate interfacing cofunctions with non-coroutine code, there will
+be a built-in function ``costart`` whose definition is equivalent to
+
+::
+
+    def costart(obj, *args, **kwds):
+        return obj.__cocall__(*args, **kwds)
+
+There will also be a corresponding C API function
+
+::
+
+    PyObject *PyObject_CoCall(PyObject *obj, PyObject *args, PyObject *kwds)
+
+It is left unspecified for now whether a cofunction is a distinct type
+of object or, like a generator function, is simply a specially-marked
+function instance. If the latter, a read-only boolean attribute
+``__iscofunction__`` should be provided to allow testing whether a given
+function object is a cofunction.
+
+
+Motivation and Rationale
+========================
+
+The ``yield from`` syntax is reasonably self-explanatory when used for
+the purpose of delegating part of the work of a generator to another
+function. It can also be used to good effect in the implementation of
+generator-based coroutines, but it reads somewhat awkwardly when used
+for that purpose, and tends to obscure the true intent of the code.
+
+Furthermore, using generators as coroutines is somewhat error-prone.
+If one forgets to use ``yield from`` when it should have been used,
+or uses it when it shouldn't have, the symptoms that result can be
+obscure and confusing.
+
+Finally, sometimes there is a need for a function to be a coroutine
+even though it does not yield anything, and in these cases it is
+necessary to resort to kludges such as ``if 0: yield`` to force it
+to be a generator.
+
+The ``codef`` and ``cocall`` constructs address the first issue by
+making the syntax directly reflect the intent, that is, that the
+function forms part of a coroutine.
+
+The second issue is addressed
+by making it impossible to mix coroutine and non-coroutine code in
+ways that don't make sense. If the rules are violated, an exception
+is raised that points out exactly what and where the problem is.
+
+Lastly, the need for dummy yields is eliminated by making the
+form of definition determine whether the function is a coroutine,
+rather than what it contains.
+
+
+Prototype Implementation
+========================
+
+An implementation in the form of patches to Python 3.1.2 can be found
+here:
+
+http://www.cosc.canterbury.ac.nz/greg.ewing/python/generators/cofunctions.html
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+
+..
+   Local Variables:
+   mode: indented-text
+   indent-tabs-mode: nil
+   sentence-end-double-space: t
+   fill-column: 70
+   coding: utf-8
+   End:


More information about the Python-checkins mailing list