Lisp-likeness
Marcin 'Qrczak' Kowalczyk
qrczak at knm.org.pl
Tue Mar 15 18:36:40 EST 2005
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
as does Ruby:
$ ruby -e '
closures = []
for i in 0..9 do
closures.push(proc {|x| x + i})
end
puts closures[5][1000]'
1009
but Lisp loses too:
> (let ((closures (make-array 10)))
(do ((i 0 (+ i 1)))
((= i 10))
(setf (svref closures i) #'(lambda (x) (+ x i))))
(funcall (svref closures 5) 1000))
1010
Scheme wins:
> (let ((closures (make-vector 10)))
(do ((i 0 (+ i 1)))
((= i 10))
(vector-set! closures i (lambda (x) (+ x i))))
((vector-ref closures 5) 1000))
1005
and what is perhaps surprising, Perl wins:
$ perl -e '
foreach my $i (0..9) {
push @closures, sub {$_[0] + $i}
}
print $closures[5](1000), "\n"'
1005
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.
--
__("< Marcin Kowalczyk
\__/ qrczak at knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
More information about the Python-list
mailing list