From: John M. Adams
Subject: What are little closures made of?
Date: 
Message-ID: <xaog0iur8pt.fsf@anarky.sogs.stsci.edu>
Hello,

I am confused.

(defun itr (f)
  (dolist (x '(1 2 3))
    (funcall f x)))

(defun foo (result)
  (itr #'(lambda (x) (nconc result (list x))))
  result)

* (foo nil)
NIL
* (foo (list 1))
(1 1 2 3)

Why doesn't the closure accumulate when result is initially bound to
nil?

-- 
John M. Adams

From: Steven M. Haflich
Subject: Re: What are little closures made of?
Date: 
Message-ID: <3A595DB1.156C1861@pacbell.net>
"John M. Adams" wrote:

> I am confused.
> 
> (defun itr (f)
>   (dolist (x '(1 2 3))
>     (funcall f x)))
> 
> (defun foo (result)
>   (itr #'(lambda (x) (nconc result (list x))))
>   result)
> 
> * (foo nil)
> NIL
> * (foo (list 1))
> (1 1 2 3)
> 
> Why doesn't the closure accumulate when result is initially bound to
> nil?

The simplest way to explain is to use C gobbledegook:  Lisp
function calls always pass arguments by value.  NCONC is a
function, and the function call to it inside the lambda
receives the current _value_ of the lexical variable RESULT.
There is no way to pass a lexical variable to a function so
that the function could modify the value to which that variable
is bound.

Your confusion has nothing really to do with closures, and that's
probably why closures are confusing you.  Consider invoking the
same experiment interpretively, without closures.

<1> (setf result nil)
nil
<2> (nconc result '(1))
(1)
<3> result
nil
<4> (setf result (nconc result '(1)))
(1)
<5> result
(1)

NCONC has no magic way to modify the value of a variable inside
another function.  All a 2-arg NCONC does when the first arg is
NIL is to return the second arg.
From: John M. Adams
Subject: Re: What are little closures made of?
Date: 
Message-ID: <xaoofx82vcl.fsf@anarky.sogs.stsci.edu>
"Steven M. Haflich" <·······@pacbell.net> writes:

> "John M. Adams" wrote:
> 
> > I am confused.
> > 
> > (defun itr (f)
> >   (dolist (x '(1 2 3))
> >     (funcall f x)))
> > 
> > (defun foo (result)
> >   (itr #'(lambda (x) (nconc result (list x))))
> >   result)
> > 
> > * (foo nil)
> > NIL
> > * (foo (list 1))
> > (1 1 2 3)
> > 
> > Why doesn't the closure accumulate when result is initially bound to
> > nil?
> 
> The simplest way to explain is to use C gobbledegook:  Lisp
> function calls always pass arguments by value.  NCONC is a
> function, and the function call to it inside the lambda
> receives the current _value_ of the lexical variable RESULT.
> There is no way to pass a lexical variable to a function so
> that the function could modify the value to which that variable
> is bound.

Why doesn't (foo (list 1)) return (1)?

-- 
John M. Adams
From: Tim Bradshaw
Subject: Re: What are little closures made of?
Date: 
Message-ID: <ey3d7doe1lo.fsf@cley.com>
* John M Adams wrote:

>> > I am confused.
>> > 
>> > (defun itr (f)
>> >   (dolist (x '(1 2 3))
>> >     (funcall f x)))
>> > 
>> > (defun foo (result)
>> >   (itr #'(lambda (x) (nconc result (list x))))
>> >   result)
>> > 
>> > * (foo nil)
>> > NIL
>> > * (foo (list 1))
>> > (1 1 2 3)
>> > 

> Why doesn't (foo (list 1)) return (1)?

When FOO is called with (list 1), then, in FOO, RESULT is a list (1).
The anonymous function passed to ITR repeatedly modifies,
destructively, this list, until it is eventually (1 1 1 2 3).  Note it
doesn't modify the *binding* of RESULT, it modifies the object to
which that binding refers.

--tim