Considering async yield from

I know there have been discussions about why yield from is not good from within an async def f(), but, now that the PEG parser allows for more easy syntax changes, why not have

async yield from some__aiter__

as equivalent to:

async for x in some__aiter__:
    yield x

There’s asymmetry in the language, and a loss of expression by loosing yield from while in async.

Parsing isn’t a problem – the old parser already supports yield from inside async def. (Try ast.parse("async def f():\n yield from g()"). The problem comes later, in the compiler: no-one’s come up with a reasonable way to implement async yield from in terms of the bytecode/VM. So for this to be considered, the first step would be for someone to demonstrate a way to do it, and then we could have a meaningful discussion about whether the implementation complexity would be worth it.

The parsing can make async yield from equivalent to async for ... without affecting affecting the code generator.

Or, the bytecode in the code generator could be exactly the same as for async for.

From what I’ve read, the problem has been the semantics between __iter__ and __atier__. Making the equivalence of async yield from with async for..., without modifying generator semantics, has not been considered so far.

This issue came up while changing a program from one async mechanism to Python async/await.

Everything was logical and went smoothly until I had to change every yield from (which worked before [Twisted, etc.]) to an async for ....

The semantics of yield from are much more complex than a simple for loop: see the full expansion here. And giving the async version of yield from different semantics than the sync version seems even more confusing and asymmetric.

1 Like

The semantics for yield are already different within an async def f():.

The semantics of for are different from those of async for.

The semantics of async yield from may be the ones that make sense within an async context, and different from those of (sync) generators.

There could also be async yield for an__aiter__, but that’s ugly.