On Tue, May 5, 2015 at 3:01 PM, Nathaniel Smith firstname.lastname@example.org wrote:
On May 5, 2015 2:14 PM, "Guido van Rossum" email@example.com wrote:
In the PEP 492 world, these concepts map as follows:
- Future translates to "something with an __await__ method" (and asyncio
Futures are trivially made compliant by defining Future.__await__ as an alias for Future.__iter__);
- "asyncio coroutine" maps to "PEP 492 coroutine object" (either defined
with `async def` or a generator decorated with @types.coroutine -- note that @asyncio.coroutine incorporates the latter);
- "either of the above" maps to "awaitable".
Err, aren't the first and third definitions above identical?
Surely we want to say: an async def function is a convenient shorthand for creating a custom awaitable (exactly like how generators are a convenient shorthand for creating custom iterators), and a Future is-an awaitable that also adds some extra methods.
The current PEP 492 proposal does endow the object returned by calling an async function (let's call it a coroutine object) with an __await__ method. And there's a good reason for this -- the bytecode generated for await treats coroutine objects special, just like the bytecode generated for yield-from treats generator objects special. The special behavior they have in common is the presence of send() and throw() methods, which are used to allow send() and throw() calls on the outer generator to be passed into the inner generator with minimal fuss. (This is the reason why "yield from X" is *not* equivalent to "for x in X: yield x".)
@Yury: I have a feeling the PEP could use more clarity here -- perhaps the section "Await Expression" should explain what the interepreter does for each type of awaitable?