<div dir="ltr">As a follow-up, Joshua updated the PEP to remove *comprehensions, and it is now accepted.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 25, 2015 at 11:42 AM, Guido van Rossum <span dir="ltr"><<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div>I'm back, I've re-read the PEP, and I've re-read the long thread with "(no subject)".<br><br></div>I think Georg Brandl nailed it:<br><br>"""<br><i>I like the "sequence and dict flattening" part of the PEP, mostly because it<br>is consistent and should be easy to understand, but the comprehension syntax<br>enhancements seem to be bad for readability and "comprehending" what the code<br>does.<br><br>The call syntax part is a mixed bag on the one hand it is nice to be<br>
consistent with the extended possibilities in literals (flattening),<br>
but on the other hand there would be small but annoying inconsistencies<br>
anyways (e.g. the duplicate kwarg case above).</i><br>"""<br><br></div>Greg Ewing followed up explaining that the inconsistency between dict flattening and call syntax is inherent in the pre-existing different rules for dicts vs. keyword args: {'a':1, 'a':2} results in {'a':2}, while f(a=1, a=2) is an error. (This form is a SyntaxError; the dynamic case f(a=1, **{'a': 1}) is a TypeError.)<br><br></div>For me, allowing f(*a, *b) and f(**d, **e) and all the other combinations for function calls proposed by the PEP is an easy +1 -- it's a straightforward extension of the existing pattern, and anybody who knows what f(x, *a) does will understand f(x, *a, y, *b). Guessing what f(**d, **e) means shouldn't be hard either. Understanding the edge case for duplicate keys with f(**d, **e) is a little harder, but the error messages are pretty clear, and it is not a new edge case.<br><br></div>The sequence and dict flattening syntax proposals are also clean and logical -- we already have *-unpacking on the receiving side, so allowing *x in tuple expressions reads pretty naturally (and the similarity with *a in argument lists certainly helps). From here, having [a, *x, b, *y] is also natural, and then the extension to other displays is natural: {a, *x, b, *y} and {a:1, **d, b:2, **e}. This, too, gets a +1 from me.<br><br></div>So that leaves comprehensions. IIRC, during the development of the patch we realized that f(*x for x in xs) is sufficiently ambiguous that we decided to disallow it -- note that f(x for x in xs) is already somewhat of a special case because an argument can only be a "bare" generator expression if it is the only argument. The same reasoning doesn't apply (in that form) to list, set and dict comprehensions -- while f(x for x in xs) is identical in meaning to f((x for x in xs)), [x for x in xs] is NOT the same as [(x for x in xs)] (that's a list of one element, and the element is a generator expression).<br><br></div>The basic premise of this part of the proposal is that if you have a few iterables, the new proposal (without comprehensions) lets you create a list or generator expression that iterates over all of them, essentially flattening them:<br><br></div> >>> xs = [1, 2, 3]<br> >>> ys = ['abc', 'def']<br></div><div> >>> zs = [99]<br></div><div> >>> [*xs, *ys, *zs]<br> [1, 2, 3, 'abc', 'def', 99]<br> >>> <br><br></div>But now suppose you have a list of iterables:<br><br></div> >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]<br></div> >>> [*xss[0], *xss[1], *xss[2]]<br> [1, 2, 3, 'abc', 'def', 99]<br> >>> <br><br></div>Wouldn't it be nice if you could write the latter using a comprehension?<br><br> >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]<br> >>> [*xs for xs in xss]<br> [1, 2, 3, 'abc', 'def', 99]<br> >>> <div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div class="gmail_extra"><br></div><div class="gmail_extra">This is somewhat seductive, and the following is even nicer: the *xs position may be an expression, e.g.:<br><br></div><div class="gmail_extra"> >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]<br> >>> [*xs[:2] for xs in xss]<br> [1, 2, 'abc', 'def', 99]<br> >>><br><br></div><div class="gmail_extra">On the other hand, I had to explore the possibilities here by experimenting in the interpreter, and I discovered some odd edge cases (e.g. you can parenthesize the starred expression, but that seems a syntactic accident).<br><br></div><div class="gmail_extra">All in all I am personally +0 on the comprehension part of the PEP, and I like that it provides a way to "flatten" a sequence of sequences, but I think very few people in the thread have supported this part. Therefore I would like to ask Neil to update the PEP and the patch to take out the comprehension part, so that the two "easy wins" can make it into Python 3.5 (basically, I am accepting two-thirds of the PEP :-). There is some time yet until alpha 2.<br><br></div><div class="gmail_extra">I would also like code reviewers (Benjamin?) to start reviewing the <a href="http://bugs.python.org/issue2292" target="_blank">patch</a>, taking into account that the comprehension part needs to be removed.<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div class="gmail_extra"><br>-- <br><div>--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)<br><br></div>
</div></font></span></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)</div>
</div>