On Wed, Nov 30, 2016 at 1:20 AM, Chris Angelico <ros...@gmail.com> wrote:
> Hmm. The thing is, comprehensions and generators are implemented with
> their own nested functions. So I would expect that their use of async
> is independent of the function they're in. But maybe we have a bug
> here?
>>>> async def spam():
> ...     def ham():
> ...         async for i in x:
> ...             pass
> ...
>>>> def ham():
> ...     async for i in x:
>   File "<stdin>", line 2
>     async for i in x:
>             ^
> SyntaxError: invalid syntax
>>>> def ham():
> ...     async def spam():
> ...         async for i in x:
> ...             pass
> ...
> Clearly the second one is correct to throw SyntaxError, and the third
> is correctly acceptable. But the first one, ISTM, should be an error
> too.

Yeah, that looks like a bug to me. Note that 'await' results in a
clear error in the first case:

>>> async def ham():
...     def spam():
...         await foo
  File "<stdin>", line 3
SyntaxError: 'await' outside async function

>> Yeah, that's what I would expect. (x async for x in foo) is
>> essentially a no-op, just like its synchronous equivalent; it takes an
>> asynchronous iterator and produces an equivalent asynchronous
>> iterator. Meanwhile, list() can't consume an async iterator because
>> the list constructor isn't a coroutine. I don't think it's generally
>> possible to "synchronify" an async iterator other than to materialize
>> it. E.g.:
>> def alist(aiterable):
>>     result = []
>>     async for value in aiterable:
>>         result.append(value)
>>     return result
>> And I find it a little disturbing that I actually can't see a better
>> way to build a list from an async iterator than that.
> Oh. Oops. That materialization was exactly what I intended to happen
> with the comprehension. Problem: Your version doesn't work either,
> although I think it probably _does_ work if you declare that as "async
> def alist".

Yes, that's what I meant.

Reply via email to