17.6 Изменение измерений массива

Следующие функции могут использоваться для изменения размера или формы массива. Их опции почти совпадают с опциями функции make-array.

[Функция] adjust-array array new-dimensions &key :element-type :initial-element :initial-contents :fill-pointer :displaced-to :displaced-index-offset

adjust-array принимает массив и те же аргументы, что и для make-array. Количество измерений, указанных в new-dimensions должно равняться рангу массива array.

adjust-array возвращает массив такого же типа и ранга, что и массив array, но с другим измерениями new-dimensions. Фактически, аргумент array модифицируется в соответствие с новыми указаниями. Но это может быть достигнуто двумя путями: модификацией массива array или созданием нового массива и модификацией аргумента array для соединения его с новым массивом.

В простейшем случае, можно указать только измерения new-dimensions и, возможно, аргумент :initial-element. Не пустые элементы массива array вставляются в новый массив. Элементы нового массива, которые не были заполнены значениями из старого массива, получают значение из :initial-element. Если аргумент не был указан, то первоначальное значение элементов не определено.

Если указан :element-type, тогда массив array должен был быть создан с указанием такого же типа. В противном случае сигнализируется ошибка. Указание :element-type в adjust-array служит только для проверки на существование ошибки несовпадения типов.

Если указаны :initial-contents или :displaced-to, тогда они обрабатываются как для make-array. В таком случае,

Если указан :fill-pointer, тогда указатель заполнения массива array принимает указанное значение. Если массив array не содержал указателя заполнения сигнализируется ошибка.

X3J13 voted in June 1988 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 может, в зависимости от реализации и аргументов, просто изменить исходный массив или создать и вернуть новый. В последнем случае исходный массив изменяется, а именно соединяется с новым массивом, и имеет новые измерения.

X3J13 voted in January 1989 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.

Если adjust-array применяется к массиву array, который соединён с другим массивом x, тогда ни массив array, ни возвращённый результат не будет соединены с x, если только такое соединения не задано явно в вызове adjust-array.

Например, предположим что массив 4-на-4 m выглядит так:

#2A( ( alpha     beta      gamma     delta )
     ( epsilon   zeta      eta       theta )
     ( iota      kappa     lambda    mu    )
     ( nu        xi        omicron   pi    ) )

Тогда результат выражения

(adjust-array m ’(3 5) :initial-element ’baz)

является массивом 3-на-5 с содержимым

#2A( ( alpha     beta      gamma     delta     baz )
     ( epsilon   zeta      eta       theta     baz )
     ( iota      kappa     lambda    mu        baz ) )

Следует отметить, что если массив a создаётся соединённым с массивом b и затем массив b передаётся в adjust-array, то массив a все ещё будет соединён с массивом b. При этом должны быть приняты во внимание правила соединения массивов и построчный порядок следования элементов.

X3J13 voted in June 1988 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 the call.