Lukasz,

On 2015-04-24 5:37 PM, Łukasz Langa wrote:

(Though maybe we should consider `await for` and `await with`? That would have 
the advantage of making it easy to scan for all suspension points by searching 
for /await/. But being a verb it doesn't read very well.)
I’m on the fence here.

OT1H, I think “await for something in a_container” and “await with 
a_context_manager():” also read pretty well. It’s also more consistent with 
being the one way of finding “yield points”.

OTOH, “await with a_context_manager():” suggests the entire statement is 
awaited on, which is not true. “async with” is more opaque in this way, it 
simply states “there are going to be implementation-specific awaits inside”. So 
it’s more consistent with “async def foo()”.

This. I also think of 'await with' as I'm awaiting on the whole statement. And I don't even know how to interpret that.

6. StopAsyncException

I'm not sure about this. The motivation given in the PEP seems to focus on the 
need for `__anext__` to be async. But is this really the right pattern? What if 
we required `ait.__anext__()` to return a future, which can either raise good 
old `StopIteration` or return the next value from the iteration when awaited? 
I'm wondering if there are a few alternatives to be explored around the async 
iterator protocol still.
So are you suggesting to pass the returned value in a future? In this case the 
future would need to be passed to __anext__, so the Cursor example from the PEP 
would look like this:

class Cursor:
     def __init__(self):
         self.buffer = collections.deque()

     def _prefetch(self):
         ...

     async def __aiter__(self):
         return self

     async def __anext__(self, fut):
         if not self.buffer:
             self.buffer = await self._prefetch()
         if self.buffer:
             fut.set_result(self.buffer.popleft())
         else:
             fut.set_exception(StopIteration)

While this is elegant, my concern is that one-future-per-iteration-step might 
be bad for performance.

Maybe consider the following. The `async def` syntax decouples the concept of a 
coroutine from the implementation. While it’s still based on generators under 
the hood, the user no longer considers his “async function” to be a generator 
or conforming to the generator protocol. From the user’s perpective, it’s 
obvious that the return below means something different than the exception:

     async def __anext__(self):
         if not self.buffer:
             self.buffer = await self._prefetch()
             if not self.buffer:
                 raise StopIteration
         return self.buffer.popleft()

So, the same way we added wrapping in RuntimeErrors for generators in PEP 479, 
we might add transparent wrapping in a _StopAsyncIteration for CO_COROUTINE.

FWIW I have to experiment more with the reference implementation,
but at the moment I'm big -1 on touching StopIteration for
coroutines.  It's used for too many things.


Thanks!

Yury
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to