The real issue here has nothing to do with closures, lexical capture or anything like that. It's a long known issue called side-effects.

Trying to program in a functional style in the presence of side-effects is bad. *for* is the main perpetrator of side-effects here, because it updates its iterating variables rather than create a new lexical environment for them.

Say:
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> ps=[]
>>> for x in range(3): ps.append( lambda y: x+y )
...
>>> ps
[<function <lambda> at 0x8389a04>, <function <lambda> at 0x8389a74>, <function <lambda> at 0x8389c34>]
>>> ps[0](1)
3
>>> ps[1](1)
3
>>> ps[2](1)
3

It also polutes the namespace by letting x live on:
>>> x
2

Even list comprehensions still suffer from the updating:
>>> xs=[lambda y:x+y for x in range(3)]
>>> xs[0](1)
3
>>> xs[1](1)
3
>>> xs[2](1)
3

No such issue with map, which truly does it the proper functional way:
>>> ys=map(lambda x: lambda y: x+y, range(3))
>>> ys[0](1)
1
>>> ys[1](1)
2
>>> ys[2](1)
3

I don't like *for* at all. It both makes it tough to get true closures and also unnecessarily pollutes the namespace with non-local variables.

So, beware of the lack of true lexical bindings associated with the evil imperative *for*! :)
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to