Lisp HUG Maillist Archive

Why and how is state retained between these function calls?

Hi,

I'm in the process of learning lisp, and stumbled upon something I
find a bit curious. While solving problem 09 of
http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html,
I try to piggyback the solution list as an argument to an auxiliary
procedure as a list of lists. I have distilled the problem down to a
couple of lines of code here:

;; What is happening here?
(defun my-wtf (lst)
  (my-wtf-aux lst (first lst) '(nil)))

(defun my-wtf-aux (lst current res)
  (format t "current: ~a res: ~b~%" current res)
  (setf (first res)
        (cons (first lst) (first res)))
  res)

(defun do-wtf ()
  (dolist (x '(1 2 3 4 5 6))
    (my-wtf (list x))))


Some how, the state of the input argument gets retained in between
calls. As can be seen in the output from lispbox here some how a list
of the inputs in binary form is built:

CL-USER> (do-wtf)
current: 1 res: (NIL)
current: 2 res: ((1))
current: 3 res: ((10 1))
current: 4 res: ((11 10 1))
current: 5 res: ((100 11 10 1))
current: 6 res: ((101 100 11 10 1))
NIL
CL-USER>

The result seem to be identical in SBCL and LispWorks, so I take this
as a sign that "ehrm, this is perfectly sane behaviour tied to what
setf really do and you dont want to do it this way in CL". I am really
curious about what's really happening. If anyone could shed some light
on this, that would make my day.

Thanx,
Rolv Seehuus


Re: Why and how is state retained between these function calls?

Hi Rolv

Short answer: you've got got '(nil) which is a constant and you're  
modifying it - self modifying code ! Head for the hills, all bets are  
off. Try replacing with a version that makes a fresh list every time:  
I.e., (cons nil nil).

Nth

--
Earth First
(we'll take care of the other planets later)

On Mar 22, 2009, at 5:45 AM, Rolv Seehuus <rolv.seehuus@gmail.com>  
wrote:

>
> Hi,
>
> I'm in the process of learning lisp, and stumbled upon something I
> find a bit curious. While solving problem 09 of
> http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html 
> ,
> I try to piggyback the solution list as an argument to an auxiliary
> procedure as a list of lists. I have distilled the problem down to a
> couple of lines of code here:
>
> ;; What is happening here?
> (defun my-wtf (lst)
>  (my-wtf-aux lst (first lst) '(nil)))
>
> (defun my-wtf-aux (lst current res)
>  (format t "current: ~a res: ~b~%" current res)
>  (setf (first res)
>        (cons (first lst) (first res)))
>  res)
>
> (defun do-wtf ()
>  (dolist (x '(1 2 3 4 5 6))
>    (my-wtf (list x))))
>
>
> Some how, the state of the input argument gets retained in between
> calls. As can be seen in the output from lispbox here some how a list
> of the inputs in binary form is built:
>
> CL-USER> (do-wtf)
> current: 1 res: (NIL)
> current: 2 res: ((1))
> current: 3 res: ((10 1))
> current: 4 res: ((11 10 1))
> current: 5 res: ((100 11 10 1))
> current: 6 res: ((101 100 11 10 1))
> NIL
> CL-USER>
>
> The result seem to be identical in SBCL and LispWorks, so I take this
> as a sign that "ehrm, this is perfectly sane behaviour tied to what
> setf really do and you dont want to do it this way in CL". I am really
> curious about what's really happening. If anyone could shed some light
> on this, that would make my day.
>
> Thanx,
> Rolv Seehuus
>


Re: Why and how is state retained between these function calls?

On Sun, Mar 22, 2009 at 1:08 PM, Gary King <gwking@metabang.com> wrote:
> Hi Rolv
>
> Short answer: you've got got '(nil) which is a constant and you're modifying
> it - self modifying code ! Head for the hills, all bets are off. Try
> replacing with a version that makes a fresh list every time: I.e., (cons nil
> nil).

Aha. Yes. Hohum. Eggsactly. It all makes sense now. As my modified
constant lives within the lexical scope of the my-wtf function... ?

Thanx! :-)
-r-


Re: Why and how is state retained between these function calls?

On Sun, Mar 22, 2009 at 8:42 AM, Rolv Seehuus <rolv.seehuus@gmail.com> wrote:

> Aha. Yes. Hohum. Eggsactly. It all makes sense now. As my modified
> constant lives within the lexical scope of the my-wtf function... ?

No, the scope is irrelevant.  As Gary said, just replace the '(NIL)
with (LIST NIL).

Edi.


Re: Why and how is state retained between these function calls?


On Mar 22, 2009, at 7:42 AM, Rolv Seehuus wrote:

>
> On Sun, Mar 22, 2009 at 1:08 PM, Gary King <gwking@metabang.com>  
> wrote:
>> Hi Rolv
>>
>> Short answer: you've got got '(nil) which is a constant and you're  
>> modifying
>> it - self modifying code ! Head for the hills, all bets are off. Try
>> replacing with a version that makes a fresh list every time: I.e.,  
>> (cons nil
>> nil).
>
> Aha. Yes. Hohum. Eggsactly. It all makes sense now. As my modified
> constant lives within the lexical scope of the my-wtf function... ?

No, it's not the scope; it's the fact that '(nil) is a constant.

What would you expect this to do?

   (setf 5 10)


Won't work, right? 5 is a constant. So is '(nil).

--me


Updated at: 2020-12-10 08:41 UTC