May 07, 2002
Copying Arrays

On, Bettina Schimanski asked how to make a copy of an array.

  I have been using setf, but just realized that this
  really just makes the new variable point to the old
  array and so when the new array is changed so is the
  old, which I would really like to avoid (a common
  programming problem to avoid). I can go through
  tediously and

   (setf (aref new-array row col) (aref old-array row col))

  for every single element, but I'm sure there is a more
  sophisticated way which I would like to learn. I have
  found a copy function for lists, readtables, trees,
  sequences, but not for arrays...

Shannon Spires replied:

  Since you have discovered copy-seq, you probably know
  it does what you want but only for one-dimensional
  arrays (vectors). You have implied by your example
  above that you're interested in two-dimensional arrays,
  for which an additional trick is needed:
;; Here's your original two-dimensional array:
(setf original-array (make-array '(10 20)))

(copy-seq original-array) --> ERROR, because it's not a sequence

(setf linearization-array (make-array 200
                            :displaced-to original-array))
;; linearization-array is identical with
;; original-array, but it's accessible as if it were
;; one-dimensional. Changes to linearization-array will
;; affect original-array.

(setf linear-copied-array (copy-seq linearization-array))
;; This is a true copy--changes here won't affect the
;; first two.  Copy-seq works because this is
;; considered a sequence.

(setf final-copied-array (make-array '(10 20)
                           :displaced-to linear-copied-array))
;; This step just makes linear-copied-array be
;; accessible as if it were two-dimensional.
  Note that although we've created 3 new arrays in
  addition to your original, only one of them consed a
  significant amount of memory. So there's no real memory
  penalty other than the obvious cost of a copy.

Marc LeBrun then came up with this function. See if you can find where the spec for adjust-array says this will make a copy (hint: " 'data region'"...).

(defun copy-array (array)
  (let ((dims (array-dimensions array)))
     (make-array dims :displaced-to array)

How to copy arrays is a perennial question on comp.lang.lisp, so if you're interested you may want to check out some of those threads, too.

(Will, thanks for giving me a pointer to this discussion. It was educational.)

Posted by jjwiseman at May 07, 2002 12:27 PM

A minor point: In LeBrun's solution, if ARRAY has an element-type other than T, you have to tell MAKE-ARRAY that element type.

(defun copy-array (array)
(let ((dims (array-dimensions array)))
(make-array dims :element-type (array-element-type arra) :displaced-to array)

Posted by: on March 11, 2006 09:14 AM
Post a comment

Email Address:


Unless you answer this question, your comment will be classified as spam and will not be posted.
(I'll give you a hint: the answer is “lisp”.)


Remember info?