One can see an array of rank *n* (an
*n*-array) as an array of lower rank where the elements are
themselves arrays (‘cells’).

We speak of the first *n-k* dimensions of the array as the
*n-k*-‘frame’ of the array, while the last *k* dimensions are
the dimensions of the *k*-‘cells’. For example, a 3-array can be
seen as a 2-array of vectors (1-arrays) or as a 1-array of matrices
(2-arrays). In each case, the vectors or matrices are the 1-cells or
2-cells of the array. This terminology originates in the J language.

The more vague concept of a ‘slice’ refers to a subset of the array
where some indices are fixed and others are left free. As a Guile data
object, a cell is the same as a ‘prefix slice’ (the first *n-k*
indices into the original array are fixed), except that a 0-cell is not
a shared array of the original array, but a 0-slice (where all the
indices into the original array are fixed) is.

Before version 2.0, Guile had a feature called ‘enclosed arrays’ to create special ‘array of arrays’ objects. The functions in this section do not need special types; instead, the frame rank is stated in each function call, either implicitly or explicitly.

- Scheme Procedure:
**array-cell-ref**`array idx …`¶ - C Function:
**scm_array_cell_ref**`(array, idxlist)`¶ If the length of

`idxlist`equals the rank*n*of`array`, return the element at`(idx …)`

, just like`(array-ref array idx …)`

. If, however, the length*k*of`idxlist`is smaller than*n*, then return the*(n-k)*-cell of`array`given by`idxlist`, as a shared array.For example:

(array-cell-ref #2((a b) (c d)) 0) ⇒ #(a b) (array-cell-ref #2((a b) (c d)) 1) ⇒ #(c d) (array-cell-ref #2((a b) (c d)) 1 1) ⇒ d (array-cell-ref #2((a b) (c d))) ⇒ #2((a b) (c d))

`(apply array-cell-ref array indices)`

is equivalent to(let ((len (length indices))) (if (= (array-rank a) len) (apply array-ref a indices) (apply make-shared-array a (lambda t (append indices t)) (drop (array-dimensions a) len))))

- Scheme Procedure:
**array-slice**`array idx …`¶ - C Function:
**scm_array_slice**`(array, idxlist)`¶ Like

`(array-cell-ref array idx …)`

, but return a 0-rank shared array into`ARRAY`if the length of`idxlist`matches the rank of`array`. This can be useful when using`ARRAY`as a place to write to.Compare:

(array-cell-ref #2((a b) (c d)) 1 1) ⇒ d (array-slice #2((a b) (c d)) 1 1) ⇒ #0(d) (define a (make-array 'a 2 2)) (array-fill! (array-slice a 1 1) 'b) a ⇒ #2((a a) (a b)). (array-fill! (array-cell-ref a 1 1) 'b) ⇒ error: not an array

`(apply array-slice array indices)`

is equivalent to(apply make-shared-array a (lambda t (append indices t)) (drop (array-dimensions a) (length indices)))

- Scheme Procedure:
**array-cell-set!**`array x idx …`¶ - C Function:
**scm_array_cell_set_x**`(array, x, idxlist)`¶ If the length of

`idxlist`equals the rank*n*of`array`, set the element at`(idx …)`

of`array`to`x`, just like`(array-set! array x idx …)`

. If, however, the length*k*of`idxlist`is smaller than*n*, then copy the*(n-k)*-rank array`x`into the*(n-k)*-cell of`array`given by`idxlist`. In this case, the last*(n-k)*dimensions of`array`and the dimensions of`x`must match exactly.This function returns the modified

`array`.For example:

(array-cell-set! (make-array 'a 2 2) b 1 1) ⇒ #2((a a) (a b)) (array-cell-set! (make-array 'a 2 2) #(x y) 1) ⇒ #2((a a) (x y))

Note that

`array-cell-set!`

will expect elements, not arrays, when the destination has rank 0. Use`array-slice`

for the opposite behavior.(array-cell-set! (make-array 'a 2 2) #0(b) 1 1) ⇒ #2((a a) (a #0(b))) (let ((a (make-array 'a 2 2))) (array-copy! #0(b) (array-slice a 1 1)) a) ⇒ #2((a a) (a b))

`(apply array-cell-set! array x indices)`

is equivalent to(let ((len (length indices))) (if (= (array-rank array) len) (apply array-set! array x indices) (array-copy! x (apply array-cell-ref array indices))) array)

- Scheme Procedure:
**array-slice-for-each**`frame-rank op x …`¶ - C Function:
**scm_array_slice_for_each**`(array, frame_rank, op, xlist)`¶ Each

`x`must be an array of rank ≥`frame-rank`, and the first`frame-rank`dimensions of each`x`must all be the same.`array-slice-for-each`calls`op`with each set of (rank(`x`) -`frame-rank`)-cells from`x`, in unspecified order.`array-slice-for-each`allows you to loop over cells of any rank without having to carry an index list or construct shared arrays manually. The slices passed to`op`are always shared arrays of`X`, even if they are of rank 0, so it is possible to write to them.This function returns an unspecified value.

For example, to sort the rows of rank-2 array

`a`

:(array-slice-for-each 1 (lambda (x) (sort! x <)) a)

As another example, let

`a`

be a rank-2 array where each row is a 2-element vector*(x,y)*. Let’s compute the arguments of these vectors and store them in rank-1 array`b`

.(array-slice-for-each 1 (lambda (a b) (array-set! b (atan (array-ref a 1) (array-ref a 0)))) a b)

`(apply array-slice-for-each frame-rank op x)`

is equivalent to(let ((frame (take (array-dimensions (car x)) frank))) (unless (every (lambda (x) (equal? frame (take (array-dimensions x) frank))) (cdr x)) (error)) (array-index-map! (apply make-shared-array (make-array #t) (const '()) frame) (lambda i (apply op (map (lambda (x) (apply array-slice x i)) x)))))