From: svspir

Subject: Re: Feedback (copy-array)

Date: 2002-5-3 14:01

> That should work fine, but of course as a matter of style it's better not > to needlessly put the intermediate results in named variables (that just > made it clearer what's going on).
Agreed.
> If you copy arrays a lot you might want to define a function like this > which will work with any shape array > > (defun copy-array (array) > (make-array > (array-dimensions array) > :displaced-to > (copy-seq > (make-array > (array-total-size array) > :displaced-to array)))) > > (or something like that--sorry for any typos, I don't have time to run this...)
Seems to work as written.
> ... > You might also want to carefully review your current spec for > adjust-array. My 2nd edition of CLtL has some interesting comments > (p458). One is that the implementation is not supposed to collapse the > chain of displacements, so the above approach will incur some overhead for > the indirections. On the other hand it also says that adjusting an array > from displaced to non-displaced requires the implementation to copy the > data. Therefore it would seem the following code might be somewhat more > efficient (assuming you care) both by reducing the indirection and because > the copying will get done internally in adjust-array, rather than having to > pass though the interface to copy-seq (with argument processing, type > checking etc overhead).
It's not clear to me from reading the hyperspec that this is always guaranteed, and I trust the hyperspec more than CLtL. However, the hyperspec _does_ offer an alternative guarantee involving adjustable-array-p. The adjustability of arrays is one of the thornier issues in Common Lisp, as described in the Hyperspec at http://www.xanalys.com/software_tools/reference/HyperSpec/Issues/iss005_w.htm The telling line is: 5. The predicate ADJUSTABLE-ARRAY-P is true if and only if ADJUST-ARRAY will return a value EQ to this array when given this array as its first argument. Therefore, it seems that calling adjust-array may or may not yield an array which is eq to the original, and since the original question was how to create an explicit copy that did NOT share storage with the original, one must be careful to call adjustable-array-p before calling adjust-array, or risk sharing storage. The fact that it's perfectly legal to call adjust-array on an array that's manifestly non-adjustable is the source of much of the confusion surrounding this issue. Here is an example copy-array function that might solve the problem. Most of this code was written by Marc; I've just renamed things a little bit: (defun copy-adjustable-array (array) "Copies any array with a guarantee that the copy will not share storage with the original. Potentially slower and/or more memory-intensive than copy-non-adjustable-array below." (make-array (array-dimensions array) :displaced-to (copy-seq (make-array (array-total-size array) :displaced-to array)))) (defun copy-non-adjustable-array (array) "Potentially faster way to copy arrays provided they are non-adjustable. Whether this is in fact faster than copy-adjustable-array is left as an exercise." (adjust-array array (array-dimensions array))) ; Yes this is oxymoronic (defun copy-array (array) "Copy any array with a guarantee that the result will not share storage with the original." (if (adjustable-array-p array) (copy-adjustable-array array) (copy-non-adjustable-array array))) -- (Mr.) Shannon Spires <sandia.gov at svspire>