From 9413a3a2e985d555f63e6af65c80e119555a645f Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 11:59:45 -0400 Subject: [PATCH 1/7] add reference to PEP 525 for async generator semantics --- peps/pep-0798.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index 4a894c2fd2f..ac180a54f07 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -217,7 +217,9 @@ generator:: for x in it: yield from expr -Since ``yield from`` is not allowed inside of async generators, the equivalent +Since ``yield from`` is not allowed inside of async generators (see the section +of :pep:`525` on `Asynchronous yield from +`__), the equivalent for ``(*expr async for x in ait())``, is more like the following (though of course this new form should not define or reference the looping variable ``i``):: From 4414457f7bb4d1b538eb47b10566aefbb467f61a Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 12:00:37 -0400 Subject: [PATCH 2/7] fix syntax highlighting in code examples from other languages --- peps/pep-0798.rst | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index ac180a54f07..ba4ad14077f 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -746,45 +746,65 @@ to what is already available in Python, but support for using unpacking syntax within comprehensions is rare. This section provides a brief summary of support for similar syntax in a few other languages. -Many languages that support comprehensions support double loops:: +Many languages that support comprehensions support double loops: + +.. code:: python # python [x for xs in [[1,2,3], [], [4,5]] for x in xs * 2] +.. code:: haskell + -- haskell [x | xs <- [[1,2,3], [], [4,5]], x <- xs ++ xs] +.. code:: julia + # julia [x for xs in [[1,2,3], [], [4,5]] for x in [xs; xs]] +.. code:: clojure + ; clojure (for [xs [[1 2 3] [] [4 5]] x (concat xs xs)] x) Several other languages (even those without comprehensions) support these operations via a built-in function/method to support flattening of nested -structures:: +structures: + +.. code:: python # python list(itertools.chain(*(xs*2 for xs in [[1,2,3], [], [4,5]]))) +.. code:: javascript + // Javascript [[1,2,3], [], [4,5]].flatMap(xs => [...xs, ...xs]) +.. code:: haskell + -- haskell concat (map (\x -> x ++ x) [[1,2,3], [], [4,5]]) +.. code:: ruby + # ruby [[1, 2, 3], [], [4, 5]].flat_map {|e| e * 2} However, languages that support both comprehension and unpacking do not tend to allow unpacking within a comprehension. For example, the following expression -in Julia currently leads to a syntax error:: +in Julia currently leads to a syntax error: + +.. code:: julia [xs... for xs in [[1,2,3], [], [4,5]]] As one counterexample, support for a similar syntax was recently added to `Civet `_. For example, the following is a valid comprehension in -Civet, making use of Javascript's ``...`` syntax for unpacking:: +Civet, making use of Javascript's ``...`` syntax for unpacking: + +.. code:: javascript for xs of [[1,2,3], [], [4,5]] then ...(xs++xs) From ef1f9d14a91f75aa66217e2a75abd75c542bf694 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 12:02:03 -0400 Subject: [PATCH 3/7] attempt to fix incorrect examples in 'How to Teach This' --- peps/pep-0798.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index ba4ad14077f..83723ff1206 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -559,7 +559,8 @@ by a similar analogy:: for x in it: out[k_expr] = v_expr - # equivalent to out = {**expr for x in it} + # equivalent to out = {**expr for x in it}, provided that expr evaluates to + # a mapping that can be unpacked with ** out = {} for x in it: out.update(expr) @@ -597,7 +598,7 @@ Similarly, we can think of ``out = {...x... for x in it}`` as equivalent to the following code, regardless of whether or not ``...x...`` uses ``*`` or ``**`` or ``:``:: - out = set() + out = set() # or out = {} for x in it: out.update({...x...}) From 9d28d79b3fb0ce1308d85e7d21541ad4a5dc616b Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 12:02:20 -0400 Subject: [PATCH 4/7] attempt to clarify some wording in 'How to Teach This' --- peps/pep-0798.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index 83723ff1206..e099c7fa8b6 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -580,15 +580,16 @@ expressions that involve unpacking:: yield from expr g = generator() -We can then generalize from these specific examples to the idea that, -wherever a non-starred comprehension/genexp would use an operator that -adds a single element to a collection, the starred would instead use -an operator that adds multiple elements to that collection. +We can then generalize from these specific examples to the idea that, wherever +a non-starred comprehension/genexp would use an operator that adds a single +element to a collection, the starred would instead use an operator that adds +multiple elements to that collection. Alternatively, we don't need to think of the two ideas as separate; instead, with the new syntax, we can think of ``out = [...x... for x in it]`` as -equivalent to the following code [#pep798-guido]_, regardless of whether or not -``...x...`` uses ``*``:: +equivalent to the following code [#pep798-guido]_ (where ``...x...`` is a +stand-in for an arbitrary expression), regardless of whether or not ``...x...`` +uses ``*``:: out = [] for x in it: From b8bb6ecf6dadab019aa7974fc87eea2b2dd8e774 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 12:07:59 -0400 Subject: [PATCH 5/7] slight wording change in 'How to Teach This' --- peps/pep-0798.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index e099c7fa8b6..8cb40f022ad 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -587,9 +587,8 @@ multiple elements to that collection. Alternatively, we don't need to think of the two ideas as separate; instead, with the new syntax, we can think of ``out = [...x... for x in it]`` as -equivalent to the following code [#pep798-guido]_ (where ``...x...`` is a -stand-in for an arbitrary expression), regardless of whether or not ``...x...`` -uses ``*``:: +equivalent to the following [#pep798-guido]_ (where ``...x...`` is a stand-in +for arbitrary code), regardless of whether or not ``...x...`` uses ``*``:: out = [] for x in it: From dcc2aec7d64564eb048836681a91cc239fd28a8c Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 12:22:58 -0400 Subject: [PATCH 6/7] remove extraneous comma --- peps/pep-0798.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index 8cb40f022ad..c5de30700e8 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -220,7 +220,7 @@ generator:: Since ``yield from`` is not allowed inside of async generators (see the section of :pep:`525` on `Asynchronous yield from `__), the equivalent -for ``(*expr async for x in ait())``, is more like the following (though of +for ``(*expr async for x in ait())`` is more like the following (though of course this new form should not define or reference the looping variable ``i``):: From f7f6c0a9a65dc3a4f4a15b9aa97e7f0c82d3b857 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 1 Aug 2025 13:04:02 -0400 Subject: [PATCH 7/7] remove link to try to make automated checks pass --- peps/pep-0798.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/peps/pep-0798.rst b/peps/pep-0798.rst index c5de30700e8..3162d56fc94 100644 --- a/peps/pep-0798.rst +++ b/peps/pep-0798.rst @@ -218,11 +218,9 @@ generator:: yield from expr Since ``yield from`` is not allowed inside of async generators (see the section -of :pep:`525` on `Asynchronous yield from -`__), the equivalent -for ``(*expr async for x in ait())`` is more like the following (though of -course this new form should not define or reference the looping variable -``i``):: +of :pep:`525` on Asynchronous ``yield from``), the equivalent for ``(*expr +async for x in ait())`` is more like the following (though of course this new +form should not define or reference the looping variable ``i``):: async def generator(): async for x in ait():