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

Marko Rauhamaa marko at pacujo.net
Sat Mar 22 19:40:44 CET 2014


Mark Lawrence <breamoreboy at yahoo.co.uk>:

> On 22/03/2014 09:09, Ian Kelly wrote:
>> Because Python as a language only has the concept of assignment, not
>> binding. I think it would be weird and confusing if variables worked
>> this way in comprehensions and nowhere else.
>
> My understanding has always been that an expression of the rhs is
> bound to a name of the lhs. So is my understanding wrong, or is the
> above wrong, or are we talking at cross purposes, or what?

Hard to say without knowing more of your understanding.

Even Scheme doesn't have purely classical variable binding because
variables can be assigned to. You will notice that right away when you
try to implement a lisp dialect; a purely binding (substituting)
implementation fails with set!/setq because there is no variable to
assign a value to.

Python variables are named memory slots you can peek and poke into. Not
so in a purely functional language where variables are physically
removed from the code before the code is executed.

Example:

    def redouble(x):
        return x + x

    redouble(17 + 4)

If Python were simply binding variables in the purely functional sense,
the interpreter would first evaluate 17 + 4 and then make a copy of the
"redouble" function substituting the result (21) for each syntactic
occurrence of x:

    def __redouble__234001942():
        return 21 + 21

The interpreter would then proceed to evaluate the variable-less
function instance.

If you leave out assignment, there is really no difference between the
two models. Only if you don't have assignment, you don't need to
complicate your computational model with memory. Instead, you deal with
things like continuations.

In fact, even "def" violates the classic functional paradigm. For
example, to calculate 10's factorial without assignments, you can do
this (even in Python):

   (lambda n: (lambda fac: fac(fac, n)) \
      (lambda fac, n: 1 if n < 2 else n * fac(fac, n - 1)))(10)


Marko



More information about the Python-list mailing list