On 17 November 2012 00:00, Terry Reedy <span dir="ltr"><<a href="mailto:tjreedy@udel.edu" target="_blank">tjreedy@udel.edu</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class="im">On 11/16/2012 4:09 AM, Andrew Barnert wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
So far, nearly everyone is discussing things which are tangential, or arguing<br>
that one of the optional variants is bad. So let me strip down the proposal,<br>
without any options in it, and expand on a use case. The syntax is:<br>
<br>
<br>
(foo(line) with open('bar') as f for line in baz(f))<br>
</blockquote>
<br></div>
OK, that's helpful. Now let me strip down my objection to this: your proposal is conceptually wrong because it mixes two distinct and different ideas -- collection definition and context management. It conflicts with a well-defined notion of long standing.<br>
<br>
To explain: in math, one can define a set explicitly by displaying the members or implicitly as a subset of based on one or more base sets. Using one version of the notation<br>
{0, 2, 4} == {2*i| i in N; i < 3}<br>
The latter is 'set-builder notation' or a 'set comprehension' (and would usually use the epsilon-like member symbol instead of 'in'). The idea goes back at least a century.<br>
<a href="https://en.wikipedia.org/wiki/Set-builder_notation" target="_blank">https://en.wikipedia.org/wiki/<u></u>Set-builder_notation</a><br>
<br>
In Python, the latter directly translates to<br>
{2*i for i in itertools.count() if i < 3} ==<br>
{i for i in range(0, 5, 2)}<br>
(Python does not require the base collection to match the result class.)<br>
Another pair of examples:<br>
{(i,j)| i in N, j in N; i+j <= 5}<br>
{(i,j) for i in count() for j in count if i+j <= 5}<br>
<br>
Similar usage in programming go back over half a century.<br>
<a href="https://en.wikipedia.org/wiki/List_comprehension" target="_blank">https://en.wikipedia.org/wiki/<u></u>List_comprehension</a><br>
While notation in both math and CS varies, the components are always input source collection variables, conditions or predicates, and an output expression.<br>
<br>
The Python reference manual documents comprehensions as an alternate atomic display form. In Chapter 6, Expressions, Section 2, Atoms,<br>
<br>
"For constructing a list, a set or a dictionary Python provides special syntax called “displays”, each of them in two flavors:<br>
either the container contents are listed explicitly, or<br>
they are computed via a set of looping and filtering instructions, called a comprehension.<br>
...<br>
list_display ::= "[" [expression_list | comprehension] "]"<br>
<etc>"<br>
A generator expression similarly represents an untyped abstract sequence, rather than a concrete class.<br>
---<br>
<br>
In summary: A context-manager, as an object with __enter__ and __exit__ methods, is not a proper component of a comprehension. For instance, replace "open('xxx')" in your proposal with a lock creation function. On the other hand, an iterable managed resource, as suggested by Mathias Panzenböck, works fine as a source. So it does work (as you noticed also).</blockquote>
<div><br></div><div>I don't follow how you made these two leaps:</div><div>* It doesn't apply to set comprehensions in *math* -> it doesn't apply to set comprehensions in *Python*</div><div>* it doesn't apply to *set* comprehensions in Python -> it doesn't apply to *any* comprehensions in Python</div>
</div></div>