Proposed new syntax

Steve D'Aprano steve+python at pearwood.info
Sun Aug 13 21:21:59 EDT 2017


On Mon, 14 Aug 2017 08:55 am, Gregory Ewing wrote:

> Steve D'Aprano wrote:
> 
>> Python's comprehensions are inspired by Haskell's, but we made different
>> choices than they did: we make the fact that a comprehension is a loop over
>> values explicit, rather than implicit, and we use words instead of cryptic
>> symbols.
> 
> The presence of the word "for" in the comprehension syntax doesn't
> by itself imply that the values are generated by a sequential loop.
> Comprehensions in Python are intended to be read declaratively.

Where is that documented?

Why not use a declarative syntax, like "select where", instead of a procedural
syntax, if the intention is to read them declaratively?


> The definition in terms of an expansion into nested loops may
> imply that if you take it absolutely literally, but when I
> devised that expansion I only meant it as a way of defining
> the result -- I didn't intend the equivalence to extend to side
> effects.

Oh, you're to blame for that expansion are you? :-)

The core devs now take it literally: Nick and (if I remember correctly) Guido
have commented that any future expansions to comprehension syntax must fit into
that nested block expansion.

In any case, whatever your intention, that equivalence *does* extend to side
effects, and it applies to generator expressions as well as comprehensions.

I wish that we had standardised on the term "generator comprehension" instead,
to emphasise that generator expressions and comprehensions share the same
syntax, the same implementation, and the same order of side-effects.

(There was a time that list comps and gen expressions had different
implementations, and consequently list comps accidentally exposed their loop
variable while gen exprs didn't, but that's been fixed in Python 3.)

I would argue that in a language like Python that allows side-effects, such a
procedural approach should be mandatory: the alternative is that code including
comprehensions would be non-deterministic. While it is conceivable that the
list comprehension:

[x for x in seq]

could generate its values in arbitrary order, that does not apply to generator
expressions, set comprehensions or dict expressions:

(x for x in seq)
{x for x in seq}
{x:None for x in seq}

- Generator expressions have to yield their values in the same 
  order as the input from seq provides them;

- set and dict comprehensions have to deal with collisions, 
  in which case the last key seen wins. If they were declarative,
  there would be no way to reason about which key was seen last.


Given the expectation that generator expressions and all three kinds of
comprehension should operate the same way, we have no choice but to read them
procedurally as a for-loop.


 

-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list