From: JScheller
Subject: [Q] How to Copy LISP Arrays?
Date: 
Message-ID: <44chch$g58@newsbf02.news.aol.com>
I've got a structure defined into which I'm putting an array that
represents the positions on a game board. I later build lists containing
these structures, but when I try to create a new structure using
copy-xxxxx, the structure I get has a reference to the original array in
the original structure instead of it's own unique array. I tried to work
around it like this...

(defun buildMoveState( sourceState marbleRow marbleCol destRow destCol
deadMarbleRow deadMarbleCol )
  "Build a new board state based on a move."
  
    ( let (( myState (copy-boardState sourceState) ) (myArray (make-array
'(7 7) ) ) )
          ( progn
            (setq myArray (boardState-board sourceState) )
            (setf (boardState-board myState) myArray )
            (incf (boardState-depth myState) )
            (setf (boardState-parent myState) sourceState)
            (setf (boardState-hValue myState) 'none)
            ( setf (aref (boardState-board sourceState) marbleRow
marbleCol) empty)
            ( setf (aref (boardState-board sourceState) deadMarbleRow
deadMarbleCol) empty)
            ( setf (aref (boardState-board sourceState) destRow destCol)
marble)
            )
          myState
          ) 
  ) 
 
...but I still wind up mangling the original state I passed in.

How does one copy the values in an array to a new, independent array?

I've been beating on this for a couple of hours and couldn't find anything
meaningful in Steele or anywhere else I've looked. Any pointers
appreciated.

Jim Scheller

From: Thomas A. Russ
Subject: Re: [Q] How to Copy LISP Arrays?
Date: 
Message-ID: <TAR.95Sep28094106@hobbes.ISI.EDU>
In article <...> ·········@aol.com (JScheller) writes:
 > I've got a structure defined into which I'm putting an array that
 > represents the positions on a game board. I later build lists containing
 > these structures, but when I try to create a new structure using
 > copy-xxxxx, the structure I get has a reference to the original array in
 > the original structure instead of it's own unique array. I tried to work
 > around it like this...

Structure copies are all only shallow copies.  That means only the top
level is copied, not any of the substructure.

To copy an array, you need to write your own loop to do it.

 > (defun buildMoveState( sourceState marbleRow marbleCol destRow destCol
 > deadMarbleRow deadMarbleCol )
 >   "Build a new board state based on a move."
 >   
 >     ( let (( myState (copy-boardState sourceState) )
 >            (myArray (make-array '(7 7) ) ) )
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
This creates a new array and causes the variable myArray to point at it.

 >           ( progn
 >             (setq myArray (boardState-board sourceState) )
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This changes myArray to point at the sourceState's array.  IT DOES NOT
COPY.  The newly allocated array has become garbage and will be
reclaimed by the garbage collector, since nothing points at it.

 >             (setf (boardState-board myState) myArray )
 >             (incf (boardState-depth myState) )
 >             (setf (boardState-parent myState) sourceState)
 >             (setf (boardState-hValue myState) 'none)
 >             ( setf (aref (boardState-board sourceState) marbleRow
 > marbleCol) empty)
 >             ( setf (aref (boardState-board sourceState) deadMarbleRow
 > deadMarbleCol) empty)
 >             ( setf (aref (boardState-board sourceState) destRow destCol)
 > marble)
 >             )
 >           myState
 >           ) 
 >   ) 
 >  
 > ...but I still wind up mangling the original state I passed in.


 > How does one copy the values in an array to a new, independent array?

For your particular case:

(dotimes (i 7)
  (dotimes (j 7)
     (setf (aref newArray i j) (aref oldArray i j))))

 > I've been beating on this for a couple of hours and couldn't find anything
 > meaningful in Steele or anywhere else I've looked. Any pointers
 > appreciated.

The key is that Lisp doesn't like to waste it's time (and space) copying
objects.  Since there is automatic storage management, sharing objects
and even parts of list structure is a natural way to do things.  C++
programmers tend to copy just about everything because it makes manual
tracking of storage much easier.

--
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Barry Margolin
Subject: Re: [Q] How to Copy LISP Arrays?
Date: 
Message-ID: <44f3jj$1hd@tools.bbnplanet.com>
In article <··········@newsbf02.news.aol.com>,
JScheller <·········@aol.com> wrote:
>How does one copy the values in an array to a new, independent array?

If it's a one-dimensional array (i.e. a vector), you can use COPY-SEQ.

Otherwise, you have to write a function that copies element-by-element.
Here's a function that should do it (it's untested):

(defun copy-array (old-array &optional new-array)
  (let* ((rank (array-rank old-array))
	 (index-list (make-list rank :initial-element 0))
         (dimensions (apply #'vector (array-dimensions old-array))))
    (unless new-array
      (setq new-array
	    (make-array dimensions
			:element-type (array-element-type old-array)
			:adjustable (array-adjustable-p old-array)
			:fill-pointer (and (array-has-fill-pointer-p old-array)
					   (fill-pointer old-array)))))
    (loop
      ;; copy an element
      (setf (apply #'aref new-array index-list)
            (apply #'aref old-array index-list))
      ;; Increment the index
      (let (temp
	    (index-pos (1- rank))) ; start with last dimension
        (loop
	  (when (minusp index-pos)
            (return-from copy-array new-array))
	  (setq temp (incf (nth index-pos index-list)))
          (if (>= temp (svref dimensions index-pos))
              ;; carry into higher dimension
	      (progn
		(setf (nth index-pos index-list) 0)
		(decf index-pos))
              ;; return from the increment loop
	      (return nil)))))))
-- 
Barry Margolin
BBN PlaNET Corporation, Cambridge, MA
······@bbnplanet.com
Phone (617) 873-3126 - Fax (617) 873-6351
From: Thorsten Schnier
Subject: Re: [Q] How to Copy LISP Arrays?
Date: 
Message-ID: <THORSTEN.95Sep30182558@Rincewind.arch.su.edu.au>
In article <··········@tools.bbnplanet.com> ······@tools.bbnplanet.com (Barry Margolin) writes:

> From: ······@tools.bbnplanet.com (Barry Margolin)
> Newsgroups: comp.lang.lisp
> Date: 28 Sep 1995 17:20:51 -0400
> Organization: BBN Planet Corp., Cambridge, MA
> 
> In article <··········@newsbf02.news.aol.com>,
> JScheller <·········@aol.com> wrote:
> >How does one copy the values in an array to a new, independent array?
> 
> If it's a one-dimensional array (i.e. a vector), you can use COPY-SEQ.
> 
> Otherwise, you have to write a function that copies element-by-element.
> Here's a function that should do it (it's untested):
> 
> (defun copy-array (old-array &optional new-array)
>   (let* ((rank (array-rank old-array))
> 	 (index-list (make-list rank :initial-element 0))
>          (dimensions (apply #'vector (array-dimensions old-array))))
>     (unless new-array
>       (setq new-array
> 	    (make-array dimensions
> 			:element-type (array-element-type old-array)
> 			:adjustable (array-adjustable-p old-array)
> 			:fill-pointer (and (array-has-fill-pointer-p old-array)
> 					   (fill-pointer old-array)))))
>     (loop
>       ;; copy an element
>       (setf (apply #'aref new-array index-list)
>             (apply #'aref old-array index-list))
>       ;; Increment the index
>       (let (temp
> 	    (index-pos (1- rank))) ; start with last dimension
>         (loop
> 	  (when (minusp index-pos)
>             (return-from copy-array new-array))
> 	  (setq temp (incf (nth index-pos index-list)))
>           (if (>= temp (svref dimensions index-pos))
>               ;; carry into higher dimension
> 	      (progn
> 		(setf (nth index-pos index-list) 0)
> 		(decf index-pos))
>               ;; return from the increment loop
> 	      (return nil)))))))
> -- 
> Barry Margolin
> BBN PlaNET Corporation, Cambridge, MA
> ······@bbnplanet.com
> Phone (617) 873-3126 - Fax (617) 873-6351


This is a very inefficient way of doing it, since you have to do many comparisons for
the different indexes. Use row-major-aref instead:

...

 (dotimes (i (array-total-size old-array))
	(setf (row-major-aref new-array i) (row-major-aref old-array i)))


(see cltl2, page 452)


For GCL, there was a patch to get row-major-aref in the GCL mailing list:


>To: GCL Mailing List <···@cli.com>
>Subject: row-major-aref for gcl
>Date: Sun, 30 Jul 1995 13:38:47 -0400
>From: Raymond Toy <···@rtp.ericsson.se>
>Content-Length: 220
>X-Lines: 9
>X-Status: 
>Status: RO
>
>GCL 2.1 is missing row-major-aref, so here are macros to add this:
>
>(defmacro row-major-aref (array idx)
>  `(system:aref1 ,array ,idx))
>
>(defsetf row-major-aref (array idx) (val)
>  `(system:aset1 ,array ,idx ,val))
>
> Ray



thorsten

----------------------------------------------------------------------- 
       \    C                                       
        \   O                                          Thorsten Schnier
         \  M                       
     /\   \ P                            Key Centre of Design Computing
    /     / U                                      University of Sydney
    \    /  T                                                  NSW 2006
     \  /   I                      
      \/    N                                   ········@arch.su.edu.au 
    DESIGN  G                      http://www.arch.su.edu.au/~thorsten/
  key centre
-- 
----------------------------------------------------------------------- 
       \    C                                       
        \   O                                          Thorsten Schnier
         \  M                       
     /\   \ P                            Key Centre of Design Computing
    /     / U                                      University of Sydney
    \    /  T                                                  NSW 2006
     \  /   I                      
      \/    N                                   ········@arch.su.edu.au 
    DESIGN  G                      http://www.arch.su.edu.au/~thorsten/
  key centre