- array-reverse array #!optional flip?procedure
We assume that array is an array and flip?, if given, is a vector of booleans whose length is the same as the dimension of array. If flip? is not given, it is set to a vector with length the same as the dimension of array, all of whose elements are #t.
array-reverse returns a new array that is specialized, mutable, or immutable according to whether array is specialized, mutable, or immutable, respectively. Informally, if (vector-ref flip? k) is true, then the ordering of multi-indices in the k'th coordinate direction is reversed, and is left undisturbed otherwise.
More formally, we introduce the function
(define flip-multi-index (let* ((domain (array-domain array)) (lowers (interval-lower-bounds->list domain)) (uppers (interval-upper-bounds->list domain))) (lambda (multi-index) (map (lambda (i_k flip?_k l_k u_k) (if flip?_k (- (+ l_k u_k -1) i_k) i_k)) multi-index (vector->list flip?) lowers uppers))))
Then if array is specialized, array-reverse returns
(specialized-array-share array domain (lambda multi-index (apply values (flip-multi-index multi-index))))
and the result inherits the safety and mutability of array.
Otherwise, if array is mutable, then array-reverse returns
(make-array domain (lambda multi-index (apply (array-getter array) (flip-multi-index multi-index))) (lambda (v . multi-index) (apply (array-setter array) v (flip-multi-index multi-index)))))
Finally, if array is immutable, then array-reverse returns
(make-array domain (lambda multi-index (apply (array-getter array) (flip-multi-index multi-index)))))
It is an error if array and flip? don't satisfy these requirements.
The following example using array-reverse was motivated by a blog post by Joe Marshall.
(define (palindrome? s) (let ((n (string-length s))) (or (< n 2) (let* ((a ;; an array accessing the characters of s (make-array (make-interval (vector n)) (lambda (i) (string-ref s i)))) (ra ;; the array accessed in reverse order (array-reverse a)) (half-domain (make-interval (vector (quotient n 2))))) (array-every char=? ;; the first half of s (array-extract a half-domain) ;; the reversed second half of s (array-extract ra half-domain)))))) (palindrome? "") => #t (palindrome? "a") => #t (palindrome? "aa") => #t (palindrome? "ab") => #f (palindrome? "aba") => #t (palindrome? "abc") => #f (palindrome? "abba") => #t (palindrome? "abca") => #f (palindrome? "abbc") => #f