Common Lisp the Language, 2nd Edition
This function may be used to resize or reshape an array. Its options are similar to those of make-array.
adjust-array array new-dimensions &key :element-type :initial-element :initial-contents :fill-pointer :displaced-to :displaced-index-offset
adjust-array takes an array and a number of other arguments as for make-array. The number of dimensions specified by new-dimensions must equal the rank of array.
adjust-array returns an array of the same type and rank as array, with the specified new-dimensions. In effect, the array argument itself is modified to conform to the new specifications, but this may be achieved either by modifying the array or by creating a new array and modifying the array argument to be displaced to the new array.
In the simplest case, one specifies only the new-dimensions and possibly an :initial-element argument. Those elements of array that are still in bounds appear in the new array. The elements of the new array that are not in the bounds of array are initialized to the :initial-element; if this argument is not provided, then the initial contents of any new elements are undefined.
If :element-type is specified, then array must be such that it could have been originally created with that type; otherwise an error is signaled. Specifying :element-type to adjust-array serves only to require such an error check.
If :initial-contents or :displaced-to is specified, then it is treated as for make-array. In this case none of the original contents of array appears in the new array.
If :fill-pointer is specified, the fill pointer of the array is reset as specified. An error is signaled if array had no fill pointer already.
X3J13 voted in June 1988 (ADJUST-ARRAY-FILL-POINTER) to clarify the treatment of the :fill-pointer argument as follows.
If the :fill-pointer argument is not supplied, then the fill pointer of the array is left alone. It is an error to try to adjust the array to a total size that is smaller than its fill pointer.
If the :fill-pointer argument is supplied, then its value must be either an integer, t, or nil. If it is an integer, then it is the new value for the fill pointer; it must be non-negative and no greater than the new size to which the array is being adjusted. If it is t, then the fill pointer is set equal to the new size for the array. If it is nil, then the fill pointer is left alone; it is as if the argument had not been supplied. Again, it is an error to try to adjust the array to a total size that is smaller than its fill pointer.
An error is signaled if a non-nil :fill-pointer value is supplied and the array to be adjusted does not already have a fill pointer.
This extended treatment of the :fill-pointer
argument to adjust-array is consistent with the previously
existing treatment of the :fill-pointer argument to make-array.
adjust-array may, depending on the implementation and the arguments, simply alter the given array or create and return a new one. In the latter case the given array will be altered so as to be displaced to the new array and have the given new dimensions.
It is not permitted to call adjust-array on an array that was not created with the :adjustable option. The predicate adjustable-array-p may be used to determine whether or not an array is adjustable.
X3J13 voted in January 1989 (ADJUST-ARRAY-NOT-ADJUSTABLE) to allow adjust-array to be applied to any array. If adjust-array is applied to an array that was originally created with :adjustable true, the array returned is eq to its first argument. It is not specified whether adjust-array returns an array eq to its first argument for any other arrays. If the array returned by adjust-array is not eq to its first argument, the original array is unchanged and does not share storage with the new array.
Under this new definition, it is wise to treat adjust-array in the same manner as delete and nconc: one should carefully retain the returned value, for example by writing
(setq my-array (adjust-array my-array ...))
rather than relying solely on a side effect.
If adjust-array is applied to an array that is displaced to another array x, then afterwards neither array nor the returned result is displaced to x unless such displacement is explicitly re-specified in the call to adjust-array.
For example, suppose that the 4-by-4 array m looks like this:
#2A( ( alpha beta gamma delta ) ( epsilon zeta eta theta ) ( iota kappa lambda mu ) ( nu xi omicron pi ) )
Then the result of
(adjust-array m '(3 5) :initial-element 'baz)
is a 3-by-5 array with contents
#2A( ( alpha beta gamma delta baz ) ( epsilon zeta eta theta baz ) ( iota kappa lambda mu baz ) )
Note that if array a is created displaced to array b and subsequently array b is given to adjust-array, array a will still be displaced to array b; the effects of this displacement and the rule of row-major storage order must be taken into account.
X3J13 voted in June 1988 (ADJUST-ARRAY-DISPLACEMENT) to clarify the interaction of adjust-array with array displacement.
Suppose that an array A is to be adjusted. There are four cases according to whether or not A was displaced before adjustment and whether or not the result is displaced after adjustment.
If array X is displaced to array Y, and array Y is displaced to array Z, and array Y is altered by adjust-array, array X must now refer to the adjusted contents of Y. This means that an implementation may not collapse the chain to make X refer to Z directly and forget that the chain of reference passes through array Y. (Caching techniques are of course permitted, as long as they preserve the semantics specified here.)
If X is displaced to Y, it is an error to adjust Y in such a way that it no longer has enough elements to satisfy X. This error may be signaled at the time of the adjustment, but this is not required.
Note that omitting the :displaced-to argument to adjust-array is
equivalent to specifying :displaced-to nil; in either case, the array is
not displaced after the call regardless of whether it was displaced before