As a follow-up, Joshua updated the PEP to remove *comprehensions, and it is now accepted.

On Wed, Feb 25, 2015 at 11:42 AM, Guido van Rossum <guido@python.org> wrote:
I'm back, I've re-read the PEP, and I've re-read the long thread with "(no subject)".

I think Georg Brandl nailed it:

"""
I like the "sequence and dict flattening" part of the PEP, mostly because it
is consistent and should be easy to understand, but the comprehension syntax
enhancements seem to be bad for readability and "comprehending" what the code
does.

The call syntax part is a mixed bag on the one hand it is nice to be
consistent with the extended possibilities in literals (flattening),
but on the other hand there would be small but annoying inconsistencies
anyways (e.g. the duplicate kwarg case above).

"""

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.)

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.

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.

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).

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:

    >>> xs = [1, 2, 3]
    >>> ys = ['abc', 'def']
    >>> zs = [99]
    >>> [*xs, *ys, *zs]
    [1, 2, 3, 'abc', 'def', 99]
    >>>

But now suppose you have a list of iterables:

    >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]
    >>> [*xss[0], *xss[1], *xss[2]]
    [1, 2, 3, 'abc', 'def', 99]
    >>>

Wouldn't it be nice if you could write the latter using a comprehension?

    >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]
    >>> [*xs for xs in xss]
    [1, 2, 3, 'abc', 'def', 99]
    >>>

This is somewhat seductive, and the following is even nicer: the *xs position may be an expression, e.g.:

    >>> xss = [[1, 2, 3], ['abc', 'def'], [99]]
    >>> [*xs[:2] for xs in xss]
    [1, 2, 'abc', 'def', 99]
    >>>

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).

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.

I would also like code reviewers (Benjamin?) to start reviewing the patch, taking into account that the comprehension part needs to be removed.

--
--Guido van Rossum (python.org/~guido)




--
--Guido van Rossum (python.org/~guido)