> 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>