Continuing this series of posts on less familiar parts of Lisp that C++ programmers might not have encountered when starting with Lisp, we have adjust-array.
I’m only going to talk about this in the absence of displaced arrays. We’ll get to a discussion of displaced array later in this series. For now, we’ll just describe a simple use of adjust-array.
This function is used to change the dimensions of an array (but not the rank of the array, i.e. the number of dimensions). When applied, adjust-array either modifies the array or returns a new array whose contents are derived from the contents of the array being adjusted. If when the original array was created, it was marked as adjustable, then adjust-array modifies the array, otherwise it returns a new array. Note that, if the input array was not adjustable, and a new array is created, the original array is destructively modified.
For each index in the array, if the new size of that dimension is smaller, elements that are no longer spanned by the new dimensions are absent from the adjusted array. If the new size of that dimension is larger, new elements are inserted into those positions that did not exist in the input array. If a particular n-tuplet of indices exists in both the input array and the adjusted array, then the contents of both arrays will be the same there.
To visualize this in two dimensions, imagine that you’ve laid out the array, populating its cells. You then overlay a second array of the same rank but different dimensions. Some rows or columns may be absent in this second array, and those elements will not appear in the second array. Some rows or columns may be present in the second array but not in the first, in which case the new elements will be filled in with a default value. Where the arrays overlap, the elements are the same.
Here are some examples using both a non-adjustable array and an adjustable array. The original array is filled with a number sequence, and the adjustment is told to fill in newly-available array slots with the number 20.
*slime-repl sbcl*
CL-USER> (let ((original-array (make-array '(3 3) :initial-contents '((1 2 3) (4 5 6) (7 8 9)) :adjustable nil))) (format t "original-array before adjust= ~A~%" original-array) (let ((new-array (adjust-array original-array '(2 4) :initial-element 20))) (format t "original-array after adjust= ~A~%" original-array) (format t "new-array= ~A~%" new-array) (format t "Arrays are same object= ~A~%" (eq new-array original-array)))) original-array before adjust= #2A((1 2 3) (4 5 6) (7 8 9)) original-array after adjust= #2A((1 2 3) (20 4 5) (6 20 9)) new-array= #2A((1 2 3 20) (4 5 6 20)) Arrays are same object= NIL NIL CL-USER> (let ((original-array (make-array '(3 3) :initial-contents '((1 2 3) (4 5 6) (7 8 9)) :adjustable t))) (format t "original-array before adjust= ~A~%" original-array) (let ((new-array (adjust-array original-array '(2 4) :initial-element 20))) (format t "original-array after adjust= ~A~%" original-array) (format t "new-array= ~A~%" new-array) (format t "Arrays are same object= ~A~%" (eq new-array original-array)))) original-array before adjust= #2A((1 2 3) (4 5 6) (7 8 9)) original-array after adjust= #2A((1 2 3 20) (4 5 6 20)) new-array= #2A((1 2 3 20) (4 5 6 20)) Arrays are same object= T NIL