From: Ivan
Subject: semi-newbie question
Date: 
Message-ID: <0fwL9.827$1a1.79871@newsread2.prod.itd.earthlink.net>
Hi all,

Trying to learn something about cellular automata, so figured I would have
an array of lists to start out with.  Ran into something I do not
understand, and am looking for an explanation as to why this is:

>(setf ce1 (make-array 5 :initial-element '(0 0 0)))
#((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
>(setf y (aref ce1 2))
(0 0 0)
>(setf (nth 2 y) 5)
5
>ce1
#((0 0 5) (0 0 5) (0 0 5) (0 0 5) (0 0 5))

(Had to type that in - am using a friend's pc)
I could understand if the 3rd element of ce1 changed when I set y, but what
is going on that all the cells have changed?

TIA.

From: Matthew Danish
Subject: Re: semi-newbie question
Date: 
Message-ID: <20021216215933.C15831@lain.cheme.cmu.edu>
On Tue, Dec 17, 2002 at 02:47:24AM +0000, Ivan wrote:
> Hi all,
> 
> Trying to learn something about cellular automata, so figured I would have
> an array of lists to start out with.  Ran into something I do not
> understand, and am looking for an explanation as to why this is:
> 
> >(setf ce1 (make-array 5 :initial-element '(0 0 0)))

You've said "make the initial value of every element be the *literal*
object (0 0 0)".  Also, initial-element is only evaluated once per call
to make-array (it is a function, after all).

> #((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
> >(setf y (aref ce1 2))
> (0 0 0)
> >(setf (nth 2 y) 5)
> 5
> >ce1
> #((0 0 5) (0 0 5) (0 0 5) (0 0 5) (0 0 5))

(a) Every element of the array is the *same* object, see above
(b) It is undefined behavior to modify a literal object, such as one
    that you obtained by quoting (').  Use LIST to create such a list.

A few other notes:

(setf (nth 2 (aref ce1 2)) 5) works, other than what I've said above, no
need for a temporary, and ...

You probably shouldn't SETF Y without first declaring it with DEFVAR or
something that establishes a variable.  Whether or not you did this
first, I do not know though.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Kenny Tilton
Subject: Re: semi-newbie question
Date: 
Message-ID: <3DFE9720.50806@nyc.rr.com>
Ivan wrote:
> Hi all,
> 
> Trying to learn something about cellular automata, so figured I would have
> an array of lists to start out with.  Ran into something I do not
> understand, and am looking for an explanation as to why this is:
> 
> 
>>(setf ce1 (make-array 5 :initial-element '(0 0 0)))
> 
> #((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
> 
>>(setf y (aref ce1 2))
> 
> (0 0 0)
> 
>>(setf (nth 2 y) 5)
> 
> 5
> 
>>ce1
> 
> #((0 0 5) (0 0 5) (0 0 5) (0 0 5) (0 0 5))
> 
> (Had to type that in - am using a friend's pc)
> I could understand if the 3rd element of ce1 changed when I set y, but what
> is going on that all the cells have changed?

See that initial-element? Make-array takes the argument (the /same/ 
list) and makes it the initial value of each array element.

By contrast:

(setf ce1 (make-array '(5 3) :initial-element 0))
(setf (aref ce1 2 2) 5)
ce1
=> #2A((0 0 0) (0 0 0) (0 0 5) (0 0 0) (0 0 0))

If you do not want a 2-d array, I /think/ you have to initialize the 
elements in a loop. But then:

     (setf (aref ce1 n) (list 0 0 0))

If you use a literal such as '(0 0 0), I believe the compiler has the 
option of using the same list each time. This is much like the way a "C" 
programmer learns not to modify literal strings.


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
  the bath water is cold." -- Lorraine Lee Cudmore
From: Nils Goesche
Subject: Re: semi-newbie question
Date: 
Message-ID: <87isxtqqsy.fsf@darkstar.cartan>
"Ivan" <·········@earthlink.net> writes:

> Trying to learn something about cellular automata, so figured I
> would have an array of lists to start out with.  Ran into
> something I do not understand, and am looking for an
> explanation as to why this is:
> 
> >(setf ce1 (make-array 5 :initial-element '(0 0 0)))

Now, every element of the array contained in CE1 is the /same/
list (0 0 0).  The /same object/ is contained in /all/ array
slots.  Note that you are /not/ allowed to change list literals
/at all/, so you are being a very bad boy in the lines ahead...

> #((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
> >(setf y (aref ce1 2))

That's fine so far.  Had you done (setf y (aref ce1 1)), however,
Y would contain the /exact same object/!

> (0 0 0)
> >(setf (nth 2 y) 5)

Now you have changed the list literal which you have put into all
array slots.  You are /not/ allowed to change list literals, but
what you have to understand is that all array slots contain the
/same/ list right from start, and as you change this one list,
all slots will see the change.

> 5
> >ce1
> #((0 0 5) (0 0 5) (0 0 5) (0 0 5) (0 0 5))
> 
> (Had to type that in - am using a friend's pc) I could
> understand if the 3rd element of ce1 changed when I set y, but
> what is going on that all the cells have changed?

What you don't understand is that all slots of your array contain
the /same/ list.  That this list is even a list literal is not so
essential in this case; you would still observe the same effect
if you had done

(let ((some-list (list 0 0 0)))
  (setq ce1 (make-array 5 :initial-element some-list)))

Do you understand now what the problem is?  If not, please say so.

Regards,
-- 
Nils G�sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Kalle Olavi Niemitalo
Subject: Re: semi-newbie question
Date: 
Message-ID: <871y4hrs8w.fsf@Astalo.y2000.kon.iki.fi>
"Ivan" <·········@earthlink.net> writes:

> Trying to learn something about cellular automata, so figured I would have
> an array of lists to start out with.

Why not a two-dimensional array?
Then you wouldn't have problems with sharing:

[1]> (defparameter *ce1* (make-array '(5 3) :initial-element 0))
*CE1*
[2]> *ce1*
#2A((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
[3]> (setf (aref *ce1* 2 2) 5)
5
[4]> *ce1*
#2A((0 0 0) (0 0 0) (0 0 5) (0 0 0) (0 0 0))
From: Rob Warnock
Subject: Re: semi-newbie question
Date: 
Message-ID: <xt2cndR3duGZWJyjXTWc3Q@giganews.com>
Ivan <·········@earthlink.net> wrote:
+---------------
| >(setf ce1 (make-array 5 :initial-element '(0 0 0)))
+---------------

Try this way:

    > (defvar ce1 (make-array 5 :initial-contents (loop for i below 5
						    collect (list 0 0 0))))
    CE1
    > ce1
    #((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))
    > (setf (nth 2 (aref ce1 1)) 5)
    5
    > ce1
    #((0 0 0) (0 0 5) (0 0 0) (0 0 0) (0 0 0))
    > 


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://www.rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Thomas A. Russ
Subject: Re: semi-newbie question
Date: 
Message-ID: <ymismwt9aum.fsf@sevak.isi.edu>
"Ivan" <·········@earthlink.net> writes:

> 
> Hi all,
> 
> Trying to learn something about cellular automata, so figured I would have
> an array of lists to start out with.  Ran into something I do not
> understand, and am looking for an explanation as to why this is:
> 
> >(setf ce1 (make-array 5 :initial-element '(0 0 0)))

:initial-element specifies a single object which is used in all of the
positions of the vector.

> #((0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0))

Each of the (0 0 0) forms points to exactly the same object.

> >(setf y (aref ce1 2))
> (0 0 0)

OK, y now points to the object that is in each position of the vector.

> >(setf (nth 2 y) 5)
> 5

Here you destructively modify the list.  Since this is a destructive
modification, the list structure itself is modified, and since this list
structure is in all positions of the vector, all of them reflect the
change.

By the way, modifying a constant list is not allowed by the standard and
can lead to unpredictable behavior.  The list used as the initial
element is a constant because it is quoted
     '(0 0 0)   is a constant and should not be destructively modified
   (list 0 0 0) is not a constant and you can do what you want with it.

> >ce1
> #((0 0 5) (0 0 5) (0 0 5) (0 0 5) (0 0 5))
> 
> (Had to type that in - am using a friend's pc)
> I could understand if the 3rd element of ce1 changed when I set y, but what
> is going on that all the cells have changed?

If this is still a bit hard to understand, then perhaps the following
example would make it easier:

(defstruct my-struct a b c)
(setf ce1 (make-array 5 :initial-element (make-my-struct :a 0 :b 0 :c 0)))
(setf y (aref ce1 2))
(setf (my-struct-b y) 5)
ce1

You will observe that all of the C values have changed, because you have
changed a part of the object that is present in all the cells.

You might want to take a look at :initial-contents instead of
:initial-element.
-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu