Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

semi-newbie question

1 view
Skip to first unread message

Ivan

unread,
Dec 16, 2002, 9:47:24 PM12/16/02
to
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.

Matthew Danish

unread,
Dec 16, 2002, 9:59:33 PM12/16/02
to
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 <mda...@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."

Nils Goesche

unread,
Dec 16, 2002, 10:15:25 PM12/16/02
to
"Ivan" <tali...@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

Kenny Tilton

unread,
Dec 16, 2002, 10:12:09 PM12/16/02
to

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

Kalle Olavi Niemitalo

unread,
Dec 17, 2002, 2:58:55 AM12/17/02
to
"Ivan" <tali...@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))

Rob Warnock

unread,
Dec 19, 2002, 8:09:24 AM12/19/02
to
Ivan <tali...@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 <rp...@rpw3.org>
627 26th Avenue <URL:http://www.rpw3.org/>
San Mateo, CA 94403 (650)572-2607


Thomas A. Russ

unread,
Dec 19, 2002, 12:28:49 PM12/19/02
to
"Ivan" <tali...@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 t...@isi.edu

0 new messages