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. -- https://mail.python.org/mailman/listinfo/python-list