On allegro-cs@cs.berkeley.edu, 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: "...new 'data region'"...).
(defun copy-array (array) (let ((dims (array-dimensions array))) (adjust-array (make-array dims :displaced-to array) dims)))
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 PMA 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)))
(adjust-array
(make-array dims :element-type (array-element-type arra) :displaced-to array)
dims)))