Lisp-likeness

Carl Banks invalidemail at aerojockey.com
Tue Mar 15 20:50:16 EST 2005


Marcin 'Qrczak' Kowalczyk wrote:
> tar at sevak.isi.edu (Thomas A. Russ) writes:
>
> >> >(defun addn (n)
> >> >	  #'(lambda (x)
> >> >	      (+ x n)))
> >>
> >> The same as
> >> def addn(n):
> >> 	def fn(x):
> >> 		return n + x
> >> 	return fn
> >
> > Is this really equivalent?
> >
> > What happens if you call addn more than once with different
> > parameters.  Will you get different functions that you can
> > use simultaneously?
>
> Yes.
>
> It also behaves correctly when a variable it refers to is later
> mutated.
>
>
> BTW, the fact that a closure refers to a variable itself rather to
its
> current value can be used to check the true attitude of languages
with
> respect to functional programming, by observing how they understand
> their basic loops :-)
>
> Python loses:
>
> >>> closures = []
> >>> for i in range(10):
> ...    def add(x):
> ...       return x + i
> ...    closures.append(add)
> ...
> >>> closures[5](1000)
> 1009


I had a minor discussion on this a couple weeks ago, wherein I
suggested that Python does it that way because nested scopes weren't
specifically done to enhance functional programming.  (It's not a
secret that Python is moving away from abstract functional support.)

For example, Python might lose when it comes to functional programming,
but it wins when it comes to nested functions like this (where a,b,c,d
are in the enclosing scope and presumably changing):

    def print_variables():
        print a,b,c,d

If Python did it the way Scheme did, this would be pretty useless.
IMO, this sort of usage is FAR more common than the functional usage as
a closure inside a loop.

Closing on a value rather than a variable would have been a lot easier
to implement.  I'm sure there was talk about which way to do it in the
discussions about adding nested scopes to the language, and if the
Python gods felt closing on a variable wasn't significantly more useful
than closing on a value, I doubt they would have done that.


> If you think it's unlikely that one would want to keep a closure
> referring to a loop control variable longer than the loop iteration
> which has created it, think about the loop body spawning a thread.

Yes, it does happen here and there.  I've needed to do that in GUI
programming.  But I would say it's not remotely as common as it other
uses, and is easy to work around:

> >>> closures = []
> >>> for i in range(10):
> ...    def defineadder(y):
> ...       def add(x):
> ...          return x + y
> ...       return add
> ...    closures.append(defineadder(i))
> ...
> >>> closures[5](1000)
> 1005


-- 
CARL BANKS




More information about the Python-list mailing list