array-displacement
array-displacement Function
Syntax:
array-displacement array → displaced-to, displaced-index-offset
Arguments and Values:
array—an array.
displaced-to—an array or nil.
displaced-index-offset—a non-negative fixnum.
Description:
If the array is a displaced array, returns the values of the :displaced-to and :displaced-index-offset options for the array (see the functions make-array and adjust-array). If the array is not a displaced array, nil and 0 are returned.
If array-displacement is called on an array for which a non-nil object was provided as the :displaced-to argument to make-array or adjust-array, it must return that object as its first value. It is implementation-dependent whether array-displacement returns a non-nil primary value for any other array.
Examples:
(setq a1 (make-array 5)) → #<ARRAY 5 simple 46115576>
(setq a2 (make-array 4 :displaced-to a1
:displaced-index-offset 1))
→ #<ARRAY 4 indirect 46117134>
(array-displacement a2)
→ #<ARRAY 5 simple 46115576>, 1
(setq a3 (make-array 2 :displaced-to a2
:displaced-index-offset 2))
→ #<ARRAY 2 indirect 46122527>
(array-displacement a3)
→ #<ARRAY 4 indirect 46117134>, 2
Exceptional Situations:
Should signal an error of type type-error if array is not an array.
See Also:
make-arrayExpanded Reference: array-displacement
Basic Usage
array-displacement returns two values: the array that the given array is displaced to, and the displacement offset. For non-displaced arrays, it returns nil and 0.
;; A non-displaced array
(array-displacement (make-array 5))
=> NIL
=> 0
;; A displaced array
(let* ((base (make-array 10 :initial-element 0))
(view (make-array 5 :displaced-to base :displaced-index-offset 3)))
(multiple-value-list (array-displacement view)))
=> (#(0 0 0 0 0 0 0 0 0 0) 3)
Verifying Displacement Relationships
You can use array-displacement to check whether an array shares storage with another.
(let* ((a (make-array 8 :initial-contents '(0 1 2 3 4 5 6 7)))
(b (make-array 4 :displaced-to a :displaced-index-offset 2)))
(multiple-value-bind (target offset) (array-displacement b)
(list :displaced-to-a (eq target a)
:offset offset)))
=> (:DISPLACED-TO-A T :OFFSET 2)
Chained Displacement
Displacement is not transitive -- if B is displaced to A, and C is displaced to B, then array-displacement on C returns B, not A.
(let* ((a (make-array 10 :initial-element 0))
(b (make-array 6 :displaced-to a :displaced-index-offset 2))
(c (make-array 3 :displaced-to b :displaced-index-offset 1)))
(multiple-value-bind (target offset) (array-displacement c)
(list :target-is-b (eq target b)
:offset offset)))
=> (:TARGET-IS-B T :OFFSET 1)
Practical Use: Checking If an Array Is a View
(defun displaced-array-p (array)
"Returns true if ARRAY is displaced to another array."
(not (null (nth-value 0 (array-displacement array)))))
(displaced-array-p (make-array 5))
=> NIL
(displaced-array-p (make-array 3 :displaced-to (make-array 10)))
=> T