I'm just playing with lambda and closure, and I don't understand why two
forms don't evaluate to the same result. I defined a dynamic variable to
hold the closure, named *incrementer*. (FWIW, I'm under SLIME with SBCL)
The first form and it's result are:
CL-USER> (setf *incrementer*
(let ((increment 3))
(lambda (x)
(+ x increment))))
#<FUNCTION (LAMBDA (X)) {C0C946D}>
Then I can do:
CL-USER> (funcall *incrementer* 1)
4
The second use involves a function to automate the creation of the
closure:
CL-USER> (defun create-incrementer (increment)
(let ((increment increment))
(lambda (x)
(+ x increment))))
CREATE-INCREMENTER
In which I copy-pasted the previous form, replacing the constant number
with the argument of the function... But:
CL-USER> (setf *incrementer* (create-incrementer 4))
#<CLOSURE (LAMBDA (X)) {C257F45}>
Which works the same way:
CL-USER> (funcall *incrementer* 1)
5
But why was one result qualified as #<FUNCTION (LAMBDA (X)) ...> and the
other as #<CLOSURE (LAMBDA (X)) ...>?
Curiously,
Nowhere man
--
···········@levallois.eu.org
OpenPGP 0xD9D50D8A
In article <······························@levallois.eu.org>,
Pierre THIERRY <···········@levallois.eu.org> wrote:
> I'm just playing with lambda and closure, and I don't understand why two
> forms don't evaluate to the same result. I defined a dynamic variable to
> hold the closure, named *incrementer*. (FWIW, I'm under SLIME with SBCL)
>
> The first form and it's result are:
>
> CL-USER> (setf *incrementer*
> (let ((increment 3))
> (lambda (x)
> (+ x increment))))
> #<FUNCTION (LAMBDA (X)) {C0C946D}>
>
> Then I can do:
>
> CL-USER> (funcall *incrementer* 1)
> 4
>
> The second use involves a function to automate the creation of the
> closure:
>
> CL-USER> (defun create-incrementer (increment)
> (let ((increment increment))
> (lambda (x)
> (+ x increment))))
> CREATE-INCREMENTER
>
> In which I copy-pasted the previous form, replacing the constant number
> with the argument of the function... But:
>
> CL-USER> (setf *incrementer* (create-incrementer 4))
> #<CLOSURE (LAMBDA (X)) {C257F45}>
>
> Which works the same way:
>
> CL-USER> (funcall *incrementer* 1)
> 5
>
> But why was one result qualified as #<FUNCTION (LAMBDA (X)) ...> and the
> other as #<CLOSURE (LAMBDA (X)) ...>?
Looks like the compiler noticed that in the first case there was no way
to modify INCREMENT, so it optimized the code into
(lambda (x) (+ x 3))
Now there's no closed variable, so it can be implemented as a normal
function. Try this:
(multiple-value-setq (*incrementer* *increment-changer*)
(let ((increment 3))
(values (lambda (x) (+ x increment))
(lambda (new) (setq increment new))))
This time *incrementer* should be a closure.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***