On Sat, Oct 16, 2021 at 11:42:49AM -0400, Erik Demaine wrote:
I guess the question is whether to define `(*it for it in its)` to mean tuple or generator comprehension or nothing at all.
I don't see why that is even a question. We don't have tuple comprehensions and `(expr for x in items)` is always a generator, never a tuple. There's no ambiguity there. Why would allowing unpacking turn it into a tuple?
It would be extremely surprising for `(*expr for x in items)` to return a tuple instead instead of a generator, or for it to be forbidden when unpacking versions of list/set/dict comprehensions are allowed.
Remember that it is *commas*, not the brackets, that make a tuple (the empty tuple excepted). The brackets around `(expr for x in items)` doesn't make it a tuple any more than the brackets in f(arg) makes a tuple.
I'd be inclined to not define `(*it for it in its)`, given the ambiguity.
The only tricky corner case is that generator comprehensions can forgo the surrounding brackets in the case of a function call:
func( (expr for x in items) ) func( expr for x in items ) # we can leave out the brackets
But with the unpacking operator, it is unclear whether the unpacking star applies to the entire generator or the inner expression:
func(*expr for x in items)
That could be read as either:
it = (expr for x in items) func(*it)
it = (*expr for x in items) func(it)
Of course we can disambiguate it with precedence rules, in the same way that there is not really any ambiguity in `-3**2` (for example). Is it minus (3 squared) or (minus 3) squared? The precedence rules are clear that it absolutely is the first, but people do tend to read it wrong.
In this case, even if the precedence rules make the "unpacking generator comprehension inside a function call" case unambiguous, it *might* be clearer to require the extra brackets:
func(*(expr for x in items)) func((*expr for x in items))
are then clearly different. (The non-unpacking case of course can remain as it is today.)
But it would be quite surprising for this minor issue to lead to the major inconsistency of prohibiting unpacking inside generator comps when it is allowed in list, dict and set comps.