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.
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."
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
"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
"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