Explanation of this Python language feature? [x for x in x for x in x] (to flatten a nested list)

Rustom Mody rustompmody at gmail.com
Sat Mar 22 01:26:26 EDT 2014


On Saturday, March 22, 2014 10:21:13 AM UTC+5:30, Chris Angelico wrote:
> On Sat, Mar 22, 2014 at 3:39 PM, Rustom Mody wrote:
> >> So if that's not going to be broken, how is this fundamentally different?
> >> def func_loop():
> >>     for x in 1,2,3:
> >>         yield (lambda: x)
> > Thats using a for-loop
> > A 'for' in a comprehension carries a different intention, the matching names
> > being merely coincidental.

> So what you're saying is that these two are fundamentally different:

> def unrolled():
>     x = 1
>     yield (lambda: x)
>     x = 2
>     yield (lambda: x)
>     x = 3
>     yield (lambda: x)

> def loop():
>     for x in 1,2,3:
>         yield (lambda: x)

Well almost...

Except that the 'loop' I am talking of is one of

def loop():
     return [yield (lambda: x) for x in [1,2,3]]
or 
     return (yield (lambda: x) for x in [1,2,3])      
or just plain ol
     (lambda x:  for x in [1,2,3])

IOW loop is an imperative construct, comprehensions are declarative

Progressing through a loop in a sequential order is natural and to
be expected

Comprehensions being declarative, progressing through them
in some order is incidental.


> In other words, a loop should be implemented as a separate binding
> each time, not a rebinding. That's an interesting point, and it does
> make some sense; effectively, what you want is for the body of a for
> loop to be a new scope, a unique scope every iteration of the loop,
> and one that automatically closes over all variables in the parent
> scope (including for assignments) except for the loop
> iteration/counter variable.

> That does make some sense, but it doesn't really fit Python's concept.

Yes it does not fit in with imperative programming.

Its good to remember the history.
Haskell did not invent comprehensions

In programming, they started with Miranda where they were called
'ZF-expressions' after the Zermelo/Fraenkel of axiomatic set theory.

Because Russell's paradox had shaken the (intended) foundations of mathematics,
the way out (actually the one chosen by Zermelo and Fraenkel) was to
add a *comprehension axiom*

http://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory#3._Axiom_schema_of_specification_.28also_called_the_axiom_schema_of_separation_or_of_restricted_comprehension.29

What this basically mandates is that set constructions like
{x | Pred(x) } are disqualified (called unrestricted comprehension)

Only
{x ∈ S | Pred(x) } is a valid.

IOW sets cannot be concocted out of the blue but only out of other sets.

Fast forward 50 years and what David Turner – inventor of Miranda –- realized 
is that if the programming language is sufficiently mathematical – ie no
imperative constructs plus lazy evaluation, then comprehensions are
actually constructive enough to make make into programming constructs.

However as Mark Harris points out imperative and functional thinking styles
remain somewhat inconsistent with each other.



More information about the Python-list mailing list