From: Dragos-Anton Manolescu
Subject: Q: copy an array
Date: 
Message-ID: <m24twq2qe6.fsf@sweetbay.will.uiuc.edu>
Hi all,

I was wondering what's the right way to copy an array in
Lisp. For example, something like:

2. Break> (setf a1 (make-array '(2 2) :initial-element 1))
#2A((1 1) (1 1))
2. Break> (setf a2 a1)
#2A((1 1) (1 1))
2. Break> (setf (aref a2 0 0) 0)
0
2. Break> a2
#2A((0 1) (1 1))
2. Break> a1
#2A((0 1) (1 1))
    ^^^

also alters a1 which is not what I want. One possible way that I see
is to call make-array and then copy element by element, but this
sounds like Basic to me.

Thanx in advance,

-- 
Dragos Manolescu                              WILL AM/FM/TV
                                              1110 W. Main Street
e-mail: ········@uiuc.edu                     Urbana, IL 61801
                                              Phone: (217)333-1070

From: Barry Margolin
Subject: Re: Q: copy an array
Date: 
Message-ID: <476685$fti@tools.bbnplanet.com>
In article <··············@sweetbay.will.uiuc.edu>,
Dragos-Anton Manolescu <········@uiuc.edu> wrote:
>2. Break> (setf a1 (make-array '(2 2) :initial-element 1))
>#2A((1 1) (1 1))
>2. Break> (setf a2 a1)
>#2A((1 1) (1 1))
>2. Break> (setf (aref a2 0 0) 0)
>0
>2. Break> a2
>#2A((0 1) (1 1))
>2. Break> a1
>#2A((0 1) (1 1))
>    ^^^
>
>also alters a1 which is not what I want. 

Of course you understand that A1 and A2 are variables which refer to the
*same* array.  Lisp is based on objects with identity independent of the
variables used to refer to them.

>					  One possible way that I see
>is to call make-array and then copy element by element, but this
>sounds like Basic to me.

Unfortunately, Common Lisp doesn't have a standard function for copying an
array.  There was a proposal once in X3J13 to extend some of the sequence
functions to work on multi-dimensional arrays, but it was not adopted.  It
also seems to me that it would make sense to allow another array of the
same dimensions as the :INITIAL-ELEMENTS argument to MAKE-ARRAY, but this
doesn't work.

For one-dimensional arrays (vectors) you can use COPY-SEQ.

It's pretty easy to write a function that calls MAKE-ARRAY and then copies
element by element using ROW-MAJOR-AREF:

(setq new-array (make-array (array-dimensions old-array)
                            :element-type (array-element-type old-array)))
(dotimes (i (array-total-size old-array))
  (setf (row-major-aref new-array i) (row-major-aref old-array i)))
-- 
Barry Margolin
BBN PlaNET Corporation, Cambridge, MA
······@bbnplanet.com
Phone (617) 873-3126 - Fax (617) 873-6351
From: ········@mail.interpac.be
Subject: Re: Q: copy an array
Date: 
Message-ID: <47nkvk$a5u@donald.interpac.be>
Hello,

······@tools.bbnplanet.com (Barry Margolin) wrote:

>In article <··············@sweetbay.will.uiuc.edu>,
>Dragos-Anton Manolescu <········@uiuc.edu> wrote:
>>2. Break> (setf a1 (make-array '(2 2) :initial-element 1))
...
>Unfortunately, Common Lisp doesn't have a standard function for copying an
>array.  There was a proposal once in X3J13 to extend some of the sequence
>functions to work on multi-dimensional arrays, but it was not adopted.  It
>also seems to me that it would make sense to allow another array of the
>same dimensions as the :INITIAL-ELEMENTS argument to MAKE-ARRAY, but this
>doesn't work.
...

Here is the copy array function I use:

#+example
(let* ((array (make-array '(2 2) :initial-element (list 0 1)))
       (array-1 (copy-array-2 array))
       (array-2 (copy-array-2 array :key #'first)))
   (setf (aref array-1 0 0) 0)
   (print array)
   (print array-1)
   (print array-2)
   (values))
(defun copy-array-2 (from-array &key to-array key)
   (unless to-array
      (setf to-array (make-array (array-dimensions from-array)
                        :element-type (array-element-type from-array)
                        :adjustable (adjustable-array-p from-array)
                        :fill-pointer (and (array-has-fill-pointer-p
from-array)
                                           (fill-pointer from-array)))))
   (dotimes (i (array-total-size from-array))
      (setf (row-major-aref to-array i)
            (if key
               (funcall key (row-major-aref from-array i))
               (row-major-aref from-array i))))
   to-array)

Francis Leboutte
Algorithme
Rue de la Charrette, 141 - 4130 Tilff - Belgium
T&FAX: 32-(0)41-883528
Internet: ········@mail.interpac.be
          ········@tractebel.be