Version 13 (modified by cowan, 6 years ago) (diff) |
---|

**This needs to be integrated with ArraySlicesBreuel, so that the slice is the basic exposed object.**

## Arrays

This is a proposal for the WG2 multidimensional arrays package. These arrays are general: that is, the components may be any Scheme object. The components of arrays may be addressed either by subscripts or in row-major order using a single index.

## Terminology

The *axes* of an array are its dimensions: a vector has one axis, a matrix has two, and so on. The *rank* of a vector is the number of axes it has.

Every array has a *shape*, which is a vector of non-negative exact integers that specify the maximum exclusive values of its axes. Thus an array with shape `#(4)` is a vector whose axis contains elements 0 to 3, and an array with shape `#(2 7)` is a 2 x 7 matrix whose rows range from 0 to 1 and whose columns range from 0 to 6 respectively. A component of the shape MAY be 0, in which case the vector has no components. A rank-0 vector's shape is `#()`, and it has exactly one component.

An array's *size* is its total number of components. This is the product of the components of the array's shape, or 1 if the shape has no components.

## Arrays and Vectors

A *Scheme vector* is an object on which `vector?` returns `#t`. It is implementation-defined whether Scheme vectors are the same as rank-1 arrays or not.

In order to make the difference less visible, wherever a procedure accepts an array argument that can or must be rank-1, it MUST also accept a Scheme vector. Likewise, wherever a procedure other than `array->vector` and `array->nested-vector` returns a result that is a rank-1 array, the result MAY be a Scheme vector, but there is no requirement for all rank-1 arrays to be Scheme vectors. However, there is no requirement for `vector?` to return `#t` on every rank-1 array either. In this proposal, we will simply speak of vectors.

Arrays with ranks other than 1 are a disjoint type from Scheme vectors and other types of Scheme objects.

## Equality

The values put into arrays are `eqv?` to the values fetched from them.

This proposal redefines `equal?` to descend into arrays as well as pairs, vectors, and strings. However, arrays cannot be `equal?` unless their shapes are `equal?`.

## Basic Procedures

`(make-array `*shape*` `[*initial-value*]`)`

Constructs and returns an array of the specified *shape*. All the components of the new array are set to *initial value* if it is specified; otherwise their values are undefined.

`(array? `*obj*`)`

Returns `#t` if *obj* is an array and `#f` otherwise. Note that if `(vector? `*obj*`)` returns `#t`, then `(array? `*obj*`)` MUST return `#t` as well.

`(array `*shape*` `*obj* ...`)`

Constructs and returns an array whose shape is *shape*. Each *obj* is used to initialize the contents of the array in row-major order.

`(array-shape `*array*`)`

Returns the shape of *array*. This MAY be the same (in the sense of `eqv?`) as other arrays of the same shape. Modifying the result of this procedure has undefined effects.

`(array-rank `*array*`)`

Returns the rank of *array*.

`(array-size `*array*`)`

Returns the size of *array*.

`(array-in-bounds? `*array*` `*subscript* ...`)`

Returns `#t` if *subscripts*, which MUST be exact integers, are valid subscripts for *array*, and #f otherwise. A subscript is valid if it is non-negative and less than the corresponding component of the shape.

`(array-ref `*array*` `*subscript* ...`)`

Returns the component of *array* specified by *subscripts*, which MUST be exact integers. It is an error to specify an invalid *subscript*.

`(array-set! `*array*` `*subscript* ...` `*value*`)`

Sets the component of *array* specified by *subscripts*, which MUST be exact integers, to *value*. Returns undefined values. It is an error to specify an invalid *subscript*.

`(array-row-major-index `*array*` `*subscript* ...`)`

Returns the row-major index to *array* that corresponds to *subscripts*. It is an error to specify an invalid *subscript*.

`(array-row-major-ref `*array*` `*index )
*

Returns the component of *array* specified by the row-major index *index*. It is an error to specify an *index* that is negative or not less than the size of the array.

`(array-row-major-set! `*array*` `*index*` `*value*`)`

Sets the component of *array* specified by *index* to *value*. Returns undefined values. It is an error to specify an *index* that is negative or not less than the size of the array.

`(array-copy `*array*`)`

Returns a new array with the same components (in the sense of `eqv?`) and shape as *array*.

`(array-map `*proc*` `*array* ...`)`

Applies *proc* to each corresponding component of the *arrays* in row-major order. It constructs and returns a new array with the same shape as *array* and containing components which are the results of the appropriate applications. All the *arrays* MUST have the same shape. *Proc* MUST accept at least as many arguments as there are arrays.

`(array-for-each `*proc*` `*array* ...`)`

Applies *proc* to each corresponding component of the *arrays* in row-major order, discarding the results. Returns undefined values. All the *arrays* MUST have the same shape. *Proc* MUST accept at least as many arguments as there are arrays.

`(array-fold `*proc*` `*nil*` `*array* ...`)`

Invokes *proc* on each component of *arrays* in row-major order. Each invocation is passed as arguments the arrays, the array indices of current component, and the result of the previous invocation, in that order. For the first invocation, *nil* is used as the final argument. Returns the result of the last invocation. All the *arrays* MUST have the same shape.

## Conversions

`(array->vector `*array*`)`

Constructs and returns a Scheme vector containing the components of *array* in row-major order.

`(array->list `*array*`)`

Constructs and returns a list containing the components of *array* in row-major order.

`(array->nested-vector `*array*`)`

Constructs and returns a Scheme vector whose components are also newly constructed Scheme vectors, and so on as far down as necessary to cover every axis of the vector. Bottom-level vectors contain the components of *array*. Thus, if *array* has rank 1, the result is a vector; if the array has rank 2, the result is a vector of vectors, and so on. It is an error if *array* has rank 0.

`(array->nested-list `*array*`)`

Constructs and returns a list whose components are also newly constructed lists, and so on as far down as necessary to cover every axis of *array*. Bottom-level lists contain the components of *array*. Thus, if *array* has rank 1, the result is a list; if the array has rank 2, the result is a list of lists, and so on. It is an error if *array* has rank 0.

`(vector->array `[*shape*]` `*vector*`)`

Constructs and returns an array with shape *shape* containing the components of *vector* in row-major order. If *shape* is omitted, the result has the same shape as *vector*.

`(list->array `[*shape*]` `*list*`)`

Constructs and returns an array with shape *shape* containing the components of *list* in row-major order. If *shape* is omitted, the result has rank 1 and a single axis equal to the length of *list*.

`(nested-vector->array `*rank*` `*nested-vector*`)`

Returns an array with rank *rank* whose components are initialized from *nested-vector*. It is an error if *nested-vector* is not rectangular. As a special case, if *rank* is 0, the sole component is *vector*, which need not be a vector.

`(nested-list->array `*rank*` `*nested-list*`)`

Returns an array with rank *rank* whose components are initialized from *nested-list*. It is an error if *nested-list* is not rectangular. As a special case, if *rank* is 0, the sole component is *nested-list*, which need not be a list.

## Advanced procedures

See AdvancedArraysCowan.