From: Samuel Meder
Subject: Lisp Internals Question
Date: 
Message-ID: <73455c$jg2$1@Masala.CC.UH.EDU>
I have the following problem: 


* (setf x nil)
Warning:  Declaring X special.

NIL
* (defun blah () (setf x '(A B)) (princ x) (setf (car x) 'C) x)

BLAH
* (blah)
(A B)
(C B)
* (blah)
(C B)
(C B)
* 

The second time I run "blah", x does not get set to (A B) again. This
seems to be independent of which lisp implementation used (have tried
cmucl, akcl and gcl). As far as I can tell it has something to do with 
setf:ing the car. The same thing happens when I do:



* (defun test () (let ((x '(A B))) (princ x) (setf (car x) 'C) x))

TEST
* (test)
(A B)
(C B)
* (test)
(C B)
(C B)

Can anyone explain this to me?

/Samuel Meder

From: Marco Antoniotti
Subject: Re: Lisp Internals Question
Date: 
Message-ID: <lwd86inwn6.fsf@copernico.parades.rm.cnr.it>
······@sina.hpc.uh.edu (Samuel Meder) writes:

> I have the following problem: 
> 
> 
> * (setf x nil)
> Warning:  Declaring X special.
> 
> NIL
> * (defun blah () (setf x '(A B)) (princ x) (setf (car x) 'C) x)
> 
> BLAH
> * (blah)
> (A B)
> (C B)
> * (blah)
> (C B)
> (C B)
> * 
> 
> The second time I run "blah", x does not get set to (A B) again. This
> seems to be independent of which lisp implementation used (have tried
> cmucl, akcl and gcl). As far as I can tell it has something to do with 
> setf:ing the car. The same thing happens when I do:
> 
> 
> 
> * (defun test () (let ((x '(A B))) (princ x) (setf (car x) 'C) x))
> 
> TEST
> * (test)
> (A B)
> (C B)
> * (test)
> (C B)
> (C B)
> 
> Can anyone explain this to me?
> 
> /Samuel Meder

I believe the problem is that the Lisp implementation you are using is
"optimizing" the constant '(<...> <...>) i.e. the cons skeleton. Tha
tis to say, when you run the second time the function, you have not
re-allocated '(A B).  This is a confusing, but a rather simple example
of a common "optimization" in CL systems.

The following version will work

* (defun blah () (setf x (list 'A 'B)) (princ x) (setf (car x) 'C) x)
BLAH
* (blah)
(A B)
(C B)
* (blah)
(A B)
(C B)
* (blah)
(A B)
(C B)
* 

As you can see, you are explicitely re-allocation the list skeleton
with the LIST call.

Cheers


-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 10 03 17, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Lawrence Troxler
Subject: Re: Lisp Internals Question
Date: 
Message-ID: <73467g$qve$1@mycroft.westnet.com>
Samuel Meder <······@sina.hpc.uh.edu> wrote:
: I have the following problem: 


: * (setf x nil)
: Warning:  Declaring X special.

: NIL
: * (defun blah () (setf x '(A B)) (princ x) (setf (car x) 'C) x)

: BLAH
: * (blah)
: (A B)
: (C B)
: * (blah)
: (C B)
: (C B)
: * 

: The second time I run "blah", x does not get set to (A B) again. This
: seems to be independent of which lisp implementation used (have tried
: cmucl, akcl and gcl). As far as I can tell it has something to do with 
: setf:ing the car. The same thing happens when I do:

I think you need to use (list A B) and not '(A B), otherwise, the setf is
changing the quoted string directly.

Larry

-- 
--  Larry Troxler  --  ··@westnet.com  --  Patterson, NY USA  --
  
From: eric dahlman
Subject: Re: Lisp Internals Question
Date: 
Message-ID: <tz43e7ecnhx.fsf@bbking.cs.colostate.edu>
······@sina.hpc.uh.edu (Samuel Meder) writes:

> I have the following problem: 

I'll try I am sure someone will correct this if I get it wrong.

> * (setf x nil)
> Warning:  Declaring X special.
> 
> NIL
> * (defun blah () (setf x '(A B)) (princ x) (setf (car x) 'C) x)

Here is your problem when you say '(a b) you are creating a constant
object which should not be modified.  This allows the compiler to make
a single copy of this and then just reuse it, there is no need to cons
at run time.  However, you are modifying the list which causes the
error.  If you had used (list 'a 'b) you would have consed up a new
list each time the function is invoked with the results you expected.  

A related problem happens with some implementations and their foreign
function interface when using floats.  If it is possible for a foreign
function to modify an argument, pass by reference, you can actually
confuse the lisp so that it thinks that 0.0 = 1.0.  Since the compiler
assumes that a given value will not change but it has.

> 
> BLAH
> * (blah)
> (A B)
> (C B)
> * (blah)
> (C B)
> (C B)
> * 
> 
> The second time I run "blah", x does not get set to (A B) again. This
> seems to be independent of which lisp implementation used (have tried
> cmucl, akcl and gcl). As far as I can tell it has something to do with 
> setf:ing the car. The same thing happens when I do:
> 
 
Same reason, messing with '(a b) which is semi-constant. 

> 
> 
> * (defun test () (let ((x '(A B))) (princ x) (setf (car x) 'C) x))
> 
> TEST
> * (test)
> (A B)
> (C B)
> * (test)
> (C B)
> (C B)
> 
> Can anyone explain this to me?
> 
> /Samuel Meder


Hope that helps,

-Eric
From: Donald Fisk
Subject: Re: Lisp Internals Question
Date: 
Message-ID: <3655A7AF.32EC005A@bt-sys.spamblock.bt.co.uk>
Samuel Meder wrote:

> I have the following problem:
>
> * (setf x nil)
> Warning:  Declaring X special.
>
> NIL
> * (defun blah () (setf x '(A B)) (princ x) (setf (car x) 'C) x)
>
> BLAH
> * (blah)
> (A B)
> (C B)
> * (blah)
> (C B)
> (C B)
> *
>
> The second time I run "blah", x does not get set to (A B) again.

This is because you've destructively modified special variable x.
Thisdoesn't seem too puzzling.

> This
> seems to be independent of which lisp implementation used (have tried
> cmucl, akcl and gcl). As far as I can tell it has something to do with
> setf:ing the car. The same thing happens when I do:
>
> * (defun test () (let ((x '(A B))) (princ x) (setf (car x) 'C) x))
>
> TEST
> * (test)
> (A B)
> (C B)
> * (test)
> (C B)
> (C B)
>
> Can anyone explain this to me?

This does seem puzzling, but there's a simple explanation.   The test
functioncontains a pointer to a particular list (a b).  After (setf (car
x) 'C) is executed the
first time the function runs, this list is is destructively modified.   In
other
words, this version of test is self-modifying code.

To avoid this, you can redefine test thus:
(defun test () (let ((x (list 'a 'b))) (princ x) (setf (car x) 'C) x))

Then, each time test is run, a new list containing a and b is created.

NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
added so that Netscape will allow it to be posted

> /Samuel Meder

--
Le Hibou (mo bheachd fh�in: my own opinion)
"it's just that in C++ and the like, you don't trust _anybody_,
and in CLOS you basically trust everybody.  the practical result
is that thieves and bums use C++ and nice people use CLOS."
 -- Erik Naggum