Description

Provides a SRFI 63 workalike

Usage

(require-extension array-lib)

Requires

Download

array-lib.egg

Documentation

The array-lib purports to be a Chicken workalike for SRFI 47, SRFI 63, SRFI 58, and the SLIB array, subarray & arraymap modules.

Discussion

The signatures of all SRFI 63 procedures are supported by this API, only with extended interpretations.

However, unlike SRFI 63, the equal? procedure is not automatically rebound! An extension, array-lib-equal, is available that provides a rebound procedure.

The SRFI 58 "sharp A" forms are supported.

Both SRFI 47 and SRFI 63 array prototype procedures are supplied, including complex prototypes (see below).

Array constructors will return the underlying storage object, rather than an array object, when the constructed array is 0-origin & rank = 1, per SRFI 63.

The array-lib operations are in general thread-safe. See array:thread-safe and array:storage-definition below for exceptions.

Dimensionality

Dimensions are an ordered sequence of the magnitude of each dimension. Dimensions maybe represented as a list, or a dimensions object. For example, '(1 2) are dimensions of a rank 2 array, with dimension one having magnitude 1 and dimension two having magnitude 2.

A Shape is an ordered sequence of Interval, [lower upper), for each dimension. A shape maybe a list of interval list or a shape object. For example, (0 1) (0 2) is a shape of a rank 2 array, with the bounds of dimension one [0 0] and dimension two [0 1].

The accepted list form of dimensions or shape for procedures taking these as tail arguments is as an 'exploded' list. Each element as an individual argument. For example, (make-array '(1 2) '(-8 -5)), not (make-array '((1 2) (-8 -5))).

All magnitudes of indices, dimensions, bounds, ranks, intervals are fixnums. Not much of a restiction from SRFI 63, just a clarification.

The dimensions '(2 1 3) are equivalent to the shape '(0 2 0 1 0 3).

An inner or outer dimension of 0 will result in an empty array. Per the SRFI 63 implementation.

Read Syntax

A SRFI 10 printer and reader is supplied.

An array specific read/print syntax is supplied: #<rank>A<elements>, where <rank> is the array dimensionality and <elements> are a rank-nested list consisting of all the elements, in row-major order.

The SRFI 10 print-form preserves the underlying storage model and shape information, unlike the #nA form, which only preserves the rank and element values. So, reading the #nA form may not reconstruct the original array.

Use (current-array-print-form ...) to select the desired form.

A limit is placed on the number of array elements printed, which may be overridden. See (current-array-print-count ...).

Parameters

parameter: (current-array-bounds-check [FLAG])

Gets or sets whether array indices are bounds-checked.

Default is #t.

parameter: (current-array-element-check [FLAG])

Gets or sets whether array elements are immediately type-checked before setting. When #f the underlying storage type performs any validation.

Default is #f.

parameter: (current-array-print-count [COUNT 50])

Gets or sets the number of array elements to print. A COUNT of #f will set the count 0, and #t will set the count to a very big number. When COUNT is a number it must a zero or positive fixnum.

parameter: (current-array-print-form [FORM 'SRFI 10])

Gets or sets the format for printing an array, either 'SRFI 10, 'A, or #f which turns off array element printing.

procedure: (array:thread-safe [FLAG])

Gets or sets the thread safety status. When #f cached values of the bounds & element check parameters are used.

Default value is #f.

procedure: (array:unsafe [FLAG])

Gets or sets the unsafe array element access status. When #t the array-ref and array-set! procedures are replaced by *array-ref and *array-set!procedures, respectively.

Default value is #f.

Dimensions

procedure: (make-array-dimensions [DIMENSION ...])

Returns a dimensions object. Without DIMENSION returns a rank 0 dimensions object.

procedure: (make-array-dimensions/rank RANK [COUNT 0])

RANK & COUNT must be >= 0.

Interpreted as the dimensions: ((- RANK 0) (- RANK 1) ... (/ COUNT (factorial RANK))). So rank 1 is (COUNT), 2 is (2 COUNT/2), 3 is (3 2 COUNT/3x2), and so on.

Dubious.

procedure: (array-dimensions? DIMENSIONS)

A set of dimensions, as produced by make-array-dimensions?

procedure: (array-dimensions-equal? DIMENSIONS1 DIMENSIONS2)

Are the dimensions the same?

procedure: (array-dimensions->shape DIMENSIONS)

Returns a new shape from the dimensions.

procedure: (array-dimensions->list DIMENSIONS)

Returns the dimensions information as a list.

procedure: (array-dimensions-rank DIMENSIONS)

Returns the dimension count #f when not dimensions.

procedure: (array-dimensions-in-bounds? DIMENSIONS INDEX ...)

Are the indices valid for this dimensions?

Shape

procedure: (make-array-shape [INTERVAL | START END ...])

Returns a shape object suitable for use with the array construction procedures. Without parameters returns a rank 0 shape object.

A shape is composed of a series of intervals, one for each dimension. An interval argument is either 2 paired arguments, START END, or a list of (START END), INTERVAL. An index is within the bounds for a dimension if START <= index < END.

The interval is on the integers. The START must be strictly less than the END. So [-5 -2) is valid but [-2 -5) is invalid. To indicate an empty dimension start = end is accepted.

procedure: (array-shape? OBJECT)

A shape, as produced by make-array-shape?

procedure: (array-shape-equal? SHAPE1 SHAPE2)

Are the shapes the same?

procedure: (array-shape->list SHAPE)

Returns the shape information as a list.

procedure: (array-shape-rank SHAPE)

Returns the dimension count or #f when not shape.

procedure: (array-shape-dimensions SHAPE)

Returns the length of each dimension of the shape as a list.

procedure: (array-shape-in-bounds? SHAPE INDEX ...)

Are the indices valid for this shape?

Predicates

procedure: (array? ARRAY)

Returns whether the object is an array object, or accepted as an array. Builtin objects are vector, string, and SRFI 4 vectors.

procedure: (array-strict? ARRAY)

Returns whether the object is only an array object.

procedure: (array-equal? ARRAY1 ARRAY2 [ELEMENT-EQUALITY equal?])

Are the two arrays equal in dimensionality and elements?

Signals an error when either of the arguments is not an array.

procedure: (array-empty? ARRAY)

Returns #t for an empty array, #f for anything else.

procedure: (array-in-bounds? ARRAY INDEX ...)

Are the indices valid for the array?

Signals an error when not an array.

procedure: (array-same-shape? ARRAY1 ARRAY2)

Do the arrays have the same shape?

procedure: (array-same-dimensions? ARRAY1 ARRAY2)

Do the arrays have the same dimensions?

procedure: (array-this-shape? ARRAY SHAPE)

Does the array have the specified shape?

procedure: (array-these-dimensions? ARRAY DIMENSIONS)

Does the array have the specified dimensions?

Condition Predicates

procedure: (exn-array-condition? OBJECT)

Some array error?

procedure: (exn-array-bounds-condition? OBJECT)

Out of range error?

procedure: (exn-array-type-condition? OBJECT)

Invalid type error?

Properties

procedure: (array-start ARRAY [RANK 0])

Returns the start, or lower bound, of ARRAY along dimension RANK, or #f when not array.

procedure: (array-end ARRAY [RANK 0])

Returns the end, one beyond the upper bound, of ARRAY along dimension RANK, or #f when not an array.

procedure: (array-count ARRAY [RANK 0])

Returns the number of elements of ARRAY along dimension RANK, or #f when not an array.

procedure: (array-length ARRAY)

Returns the actual number of elements (the storage length) of ARRAY, or 0 when not an array.

procedure: (array-rank ARRAY)

Returns the number of dimensions for ARRAY, or 0 when not an array, an empty array, or a rank 0 array.

procedure: (array-dimensions ARRAY)

Returns the list of dimensions for ARRAY, or #f when not an array. The elements are the actual length of each dimension, so a dimension of 3, [0 3), is 3 and [1 3) is 2.

procedure: (array-dimensions-object ARRAY)

Returns a dimensions object for ARRAY, or #f when not an array.

procedure: (array-bounds ARRAY)

Returns the bounds list for ARRAY, or #f when not an array. A list of pairs, one for each dimension. Each pair is the interval [low high].

procedure: (array-shape ARRAY)

Returns the shape list for ARRAY, or #f when not an array. The list can be used as (apply make-array-shape LIST).

To access the compiled shape information of an array use (array-bounds ...).

procedure: (array-shape-object ARRAY)

Returns a shape object for ARRAY, or #f when not an array.

procedure: (array-prototype ARRAY)

Returns the underlying prototype object for ARRAY , or #f when not an array.

This is not the original prototype object, it will not have an initial value.

procedure: (array-store ARRAY)

Returns the underlying storage object for ARRAY , or #f when not an array.

Be vewy, vewy, careful.

Constructors

A PROTOTYPE is any object such that (array? PROTOTYPE) => #t. The PROTOTYPE provides a storage definition, and an initial value - the origin element. When the PROTOTYPE is empty the initial value is unspecified.

When the PROTOTYPE is missing, '#() is assumed.

An empty array cannot be used with any setter or getter. However, property queries will work, and they can be used as a PROTOTYPE.

procedure: (array [PROTOTYPE] SHAPE/DIMENSIONS [ELEMENT ...])

Returns a fresh array of storage type PROTOTYPE with dimensionality SHAPE/DIMENSIONS and optional ELEMENT ....

When PROTOTYPE is not supplied vector is assumed. When ELEMENT ... are not supplied an empty array is returned.

procedure: (make-array [PROTOTYPE] [SHAPE/DIMENSIONS] | [INTERVAL/DIMENSION ...])

Creates and returns an array of type prototype with supplied dimensionality, and filled with elements from prototype.

(make-array [<prototype>]) will construct a rank 0 array.

(make-array [<prototype>] 0) will construct an empty array.

procedure: (array-copy [PROTOTYPE] ARRAY)

Returns a copy of the array.

When PROTOTYPE is missing a deep copy is returned of the ARRAY.

When the PROTOTYPE and ARRAY are the same, (eq? PROTOTYPE ARRAY), a fresh array is returned with the same shape, using ARRAY as the prototype.

When the PROTOTYPE is #t a fresh array is returned, with prototype ARRAY and the elements of the ARRAY.

Otherwise a fresh array is returned from the specified prototype and elements of the ARRAY.

The prototype and source array element types must be assignment compatible. Even so, precision maybe lost.

procedure: (make-shared-array ARRAY MAPPER [SHAPE/DIMENSIONS] | [INTERVAL/DIMENSION ...])

Returns a new array mapped from ARRAY. Can be used to create shared subarrays.

The MAPPER is a function that translates coordinates in the new array into coordinates in the ARRAY. A mapper must be linear, and its' range must stay within the bounds of the array, but it can be otherwise arbitrary.

procedure: (array-align ARRAY LOWER-BOUND ...)

Returns a shared-array mapped from ARRAY with new lower bounds, but same rank & dimensions.

LOWER-BOUND may be #f, for same lower-bound as the ARRAY, or an integer, for a new lower-bound. When missing 0 is assumed. Thus, (array-align ARRAY) returns a shared-array with all lower-bounds of 0.

procedure: (list->array SHAPE/DIMENSIONS/RANK [PROTOTYPE] LIST)

The list must be a rank-nested list consisting of all the elements, in row-major order, of the array to be created.

Returns an array of rank, or shape, or dimensions and type prototype consisting of all the elements, in row-major order, of the list. When the rank is 0, list is the lone array element; not necessarily a list.

procedure: (vector->array VECTOR [PROTOTYPE] [SHAPE/DIMENSIONS] | [INTERVAL/DIMENSION ...])

The vector must be of length equal to the product of the dimensions, or shape element sizes.

Returns an array of type prototype consisting of all the elements, in row-major order, of the vector. In the case of a rank 0 array, the vector has a single element.

Conversion

procedure: (array->list ARRAY)

Returns the array elements as a rank-nested list. For rank 0 arrays returns just the element. Will generate an error when not an array.

procedure: (array->vector ARRAY)

Returns the array elements as a new unpacked vector. Will generate an error when not an array.

Accessors

SRFI 17 is supported.

procedure: (array-ref ARRAY INDEX ...)

Returns the array element at indices.

Generates an error when not an array or out-of-range condition.

procedure: (array-set! ARRAY OBJECT INDEX ...)

Sets the array element at indices to the object.

Generates an error when not an array, out-of-range condition, or the object is unsuitable as an array element.

procedure: (*array-ref ARRAY INDEX ...)

Returns the array element at indices.

Be vewy, vewy, careful.

procedure: (*array-set! ARRAY OBJECT INDEX ...)

Sets the array element at indices to the object.

Be vewy, vewy, careful.

I/O

procedure: (array-print ARRAY [COUNT <very-big-number>] [PORT (current-output-port)])

Prints COUNT elements of the ARRAY on the specified PORT.

Subarray Operations

Usage

(require-extension array-lib-sub)
procedure: (subarray ARRAY SELECT ...)

Returns a subarray sharing elements with ARRAY. For an array of rank N, there must be at least N SELECT arguments. For 0 <= I < N, SELECT[I] is either an integer, a list of two integers within the range for the Ith index, or #f.

When SELECT[I] is a list of two integers, then the Ith index is restricted to that subrange in the returned array. When the subrange is reversed, the lower bound is greater than the upper bound, the subarray is reflected.

The lower bounds for the subarray are the same as the original array. For example, the orginal array has bounds [0 2] and select (1 2), then the subarray has bounds [0 1]. Or, the orginal array has bounds [-2 0] and select (-1 0), then the subarray has bounds [-2 -1].

When SELECT[I] is #f, then the full range of the Ith index is accessible in the returned array. An elided argument is equivalent to #f.

When SELECT[I] is an integer, then the rank of the returned array is less than ARRAY, and only elements whose Ith index equals SELECT[I] are shared.

procedure: (array-trim ARRAY TRIM ...)

Returns a subarray sharing elements with ARRAY except for slices removed from either side of each dimension. Each of the TRIM arguments is an exact integer indicating how much to trim. A positive TRIM trims the data from the lower end and reduces the upper bound of the result; a negative TRIM trims from the upper end and increases the lower bound.

procedure: (array-row-ref ARRAY INDEX ...)

Returns the array row, as an unpacked vector, at indices. Will generate an error when not an array or out-of-range condition. The number of indices must be one less than the rank.

procedure: (array-row-set! ARRAY OBJECT INDEX ...)

Sets the array row at indices to the object. Will generate an error when not an array, out-of-range condition, or the object is unsuitable as an array row. The number of indices must be one less than the rank.

The row object may be an one dimensional array, a list, or an atomic value. The row object length must match the target array row length. When an atomic value this operation is row fill.

procedure: (array-split ARRAY OUTER-RANK)

Return a list of fresh subarrays, split along the specified outer rank, in ascending order by outer index.

procedure: (array-split/shared ARRAY OUTER-RANK)

Return a list of shared subarrays, split along the specified outer rank, in ascending order by outer index.

procedure: (array-join PROTOTYPE OUTER-SHAPE/DIMENSIONS [INNER-SHAPE/DIMENSIONS] ARRAY ...)

Construct a fresh array with specified prototype, outer dimensions, and optional inner dimensions, from the specified inner array(s).

The outer dimension maybe a number (indicating the single, outer, dimension), a list of dimensions, a shape, or #f (indicating the count of the inner arrays is the outer dimension).

If specified the inner dimension maybe a list of dimensions, or a shape. If missing the first inner array shape is used as the inner shape for the result array.

The result array shape is the concatenation of the outer and inner shapes. The rank of the result array must be greater than the rank the inner array(s).

All joined arrays must be of the same dimensionality.

procedure: (array-reverse ARRAY)

Returns a fresh array with the top-level dimension reversed.

Higher Order Operations

Usage

(require-extension array-lib-hof)
procedure: (make-array-index-generator SHAPE/DIMENSIONS/ARRAY)

Returns a zero argument procedure which returns an indices list (a full index) for the specified bounds upon each invocation, or #f when the indices are exhausted.

An indices list is suitable for use with (apply array-ref/array-set! ... indices).

procedure: (array-for-each-index PROCEDURE [SHAPE/DIMENSIONS/ARRAY ...])

Invokes the procedure with each set of indices for the specified bounds. The procedure arity is equal to the number of bounds. Each argument is a list of the indices, with rank length (length of the bounds).

When an array is specified the bounds of the array are used.

An indices list is suitable for use with (apply array-ref/array-set! ... indices).

All arrays should be of the same dimensions. The operation will terminate when any of the set of indices is exhausted.

procedure: (array-index-map! ARRAY PROCEDURE)

Applys the PROCEDURE to each list of indexes of the ARRAY and replaces the existing element with the result of the procedure application.

procedure: (array-indexes ARRAY)

Returns an array of lists of indexes for the ARRAY.

procedure: (array-for-each PROCEDURE ARRAY ...)

Apply the procedure to each element of the array(s). The procedure arity is equal to the number of the array(s).

All arrays must be of the same dimensionality.

procedure: (array-map! DESTINATION-ARRAY PROCEDURE SOURCE-ARRAY ...)

Apply the procedure to each element of SOURCE-ARRAY .... The procedure arity is equal to the number of the source array(s).

Returns the DESTINATION-ARRAY with the mapped elements. An in-place map.

All arrays must be of the same dimensionality.

procedure: (array-map PROTOTYPE PROCEDURE ARRAY ...)

Apply the procedure to each element of the array(s). The procedure arity is equal to the number of the array(s).

Returns a fresh array from the PROTOTYPE and the shape of the first ARRAY with the mapped elements.

All arrays must be of the same dimensionality.

procedure: (array-fold PROCEDURE SEED ARRAY ...)

Apply the fold procedure to each element of the array(s). The procedure arity is 1 + the number of array(s). The first argument is the current accumulated value, or the initial seed. The rest of the arguments are the array elements.

Returns the accumulated value.

All arrays must be of the same dimensionality.

procedure: (array-unfold PROTOTYPE RANK/SHAPE/DIMENSIONS PROCEDURE SEED ...)

Returns a new array from the PROTOTYPE, the dimensionality RANK/SHAPE/DIMENSIONS, and elements from the result values of interated invocations of PROCEDURE.

The number of seeds must equal the number of elements in the inner-most row of the new array.

PROCEDURE has a signature ((ROW-NO fixnum) (SEED-1 object) ... (SEED-N object) -> (values (ELEMENT-1 object) ... (ELEMENT-N object))). The values of the previous invocation are the arguments of the next.

procedure: (array-reshape PROTOTYPE RANK/SHAPE/DIMENSIONS PROCEDURE ARRAY)

Conform an N dimensional source ARRAY to a fresh M dimensional target array.

The PROCEDURE takes 2 arguments, the target row vector and the source row vector. The target vector length is M and the source vector is length N. The procedure is not required to use the supplied target vector. However, it must return some vector of length M.

Returns the new array.

procedure: (array-reshape/shared ARRAY [SHAPE/DIMENSIONS] | [INTERVAL/DIMENSION ...])

Conform an N dimensional source ARRAY to a shared M dimensional target array. Returns the shared-array.

A DIMENSION maybe #f to indicate a dimension as large as necessary to fill the array. An INTERVAL maybe (LOWER-BOUND #f) to indicate an interval as large as necessary to fill the array. The dimensions of the shared array may be arbitrary but must lay within the source array.

Bug - Re-shaping a shared-array does not yield a correct result.

procedure: (array-copy! DESTINATION-ARRAY SOURCE-ARRAY)

Copy the elements of the source array to the corresponding elements of the destination array. The source and destination arrays must have the same dimensions, but not necessarily the same shape.

The source and destination element types must be assignment compatible. Even so, precision maybe lost.

Eager Comprehension

Usage

(require-extension array-lib-ec)
macro: (array-ec PROTOTYPE SHAPE/DIMENSIONS [QUALIFIER ...] EXPRESSION)

Returns an array with specified PROTOTYPE, and SHAPE/DIMENSIONS. Each element of the fresh array is produced by evaluating the EXPRESSION for every state generated by the set of QUALIFIER.

Should more states be generated than elements of the array they are ignored.

macro: (:array VARIABLE [(index INDEX-VARIABLE ...)] ARRAY ...)

Generate each element of each ARRAY, binding the element to VARIABLE. Should the indices be wanted there must be as many INDEX-VARIABLE items as the rank of greatest dimensioned array.

Prototypes

SRFI 63

procedure: (A:floC128b [INITIAL])

Returns an inexact 128 bit flonum complex uniform-array prototype.

procedure: (A:floC64b [INITIAL])

Returns an inexact 64 bit flonum complex uniform-array prototype.

procedure: (A:floC32b [INITIAL])

Returns an inexact 32 bit flonum complex uniform-array prototype.

procedure: (A:floC16b [INITIAL])

Returns an inexact 16 bit flonum complex uniform-array prototype.

procedure: (A:floR128b [INITIAL])

Returns an inexact 128 bit flonum real uniform-array prototype.

procedure: (A:floR64b [INITIAL])

Returns an inexact 64 bit flonum real uniform-array prototype.

procedure: (A:floR32b [INITIAL])

Returns an inexact 32 bit flonum real uniform-array prototype.

procedure: (A:floR16b [INITIAL])

Returns an inexact 16 bit flonum real uniform-array prototype.

procedure: (A:floQ128d [INITIAL])

Returns an exact 128 bit decimal flonum rational uniform-array prototype.

procedure: (A:floQ64d [INITIAL])

Returns an exact 64 bit decimal flonum rational uniform-array prototype.

procedure: (A:floQ32d [INITIAL])

Returns an exact 32 bit decimal flonum rational uniform-array prototype.

procedure: (A:fixZ64b [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 64 bits of precision.

procedure: (A:fixZ32b [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 32 bits of precision.

procedure: (A:fixZ16b [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 16 bits of precision.

procedure: (A:fixZ8b [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 8 bits of precision.

procedure: (A:fixN64b [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 64 bits of precision.

procedure: (A:fixN32b [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 32 bits of precision.

procedure: (A:fixN16b [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 16 bits of precision.

procedure: (A:fixN8b [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 8 bits of precision.

procedure: (A:bool [INITIAL])

Returns a boolean uniform-array prototype.

SRFI 47

procedure: (ac64 [INITIAL])

Returns an inexact 64 bit flonum complex uniform-array prototype.

procedure: (ac32 [INITIAL])

Returns an inexact 32 bit flonum complex uniform-array prototype.

procedure: (ar64 [INITIAL])

Returns an inexact 64 bit flonum real uniform-array prototype.

procedure: (ar32 [INITIAL])

Returns an inexact 32 bit flonum real uniform-array prototype.

procedure: (as64 [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 64 bits of precision.

procedure: (as32 [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 32 bits of precision.

procedure: (as16 [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 16 bits of precision.

procedure: (as8 [INITIAL])

Returns an exact binary fixnum uniform-array prototype with at least 8 bits of precision.

procedure: (au64 [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 64 bits of precision.

procedure: (au32 [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 32 bits of precision.

procedure: (au16 [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 16 bits of precision.

procedure: (au8 [INITIAL])

Returns an exact non-negative binary fixnum uniform-array prototype with at least 8 bits of precision.

procedure: (at1 [INITIAL])

Returns a boolean uniform-array prototype.

Storage Definition

procedure: (array:storage-definition SYMBOL ELEMENT-PREDICATE MAKE-TYPE TYPE-PREDICATE ELEMENT-REF ELEMENT-SET INSTANCE-LENGTH [TO-LIST [FROM-LIST [PROTOTYPE]]])

Creates or updates a non-builtin array storage class. Not Thread Safe.

SYMBOL Symbolic name of the type.
ELEMENT-PREDICATE Single argument procedure to test if an object is valid as an element of the type.
MAKE-TYPE Single argument procedure to make an instance of the type with length.
TYPE-PREDICATE Single argument procedure to test if an object is a type instance.
ELEMENT-REF Two argument procedure to get an element of a type instance.
ELEMENT-SET Three argument procedure to set an element of a type instance.
INSTANCE-LENGTH Single argument procedure to return the length of the type instance.
TO-LIST Single argument procedure
FROM-LIST Single argument procedure
PROTOTYPE When supplied a type instance. Otherwise the MAKE-TYPE procedure is used to construct an empty instance.
procedure: (array:storage-definition-prototypes)

Returns an association list of the symbolic names & prototypes of the current storage definitions. Thread Safe.

Issues

SRFI 25 indexing is 2.4 times faster! However, 'array-lib' has faster indexing than the reference SRFI 63 implementation.

Array aggregate operations are implemented in an element by element fashion.

The SRFI 42 general dispatcher (: ...) does not recognize arrays.

The 128-bit & 64-bit prototypes are currently implemented as unpacked vectors.

Full SRFI 58 implementation except for the '#<dimensions>...' form.

Doesn't print full SRFI 58 form.

Examples

(use array-lib)

(current-array-print-form 'A)

(array-dimensions (make-array 3 5))	; => (3 5)

(define fred (make-array '#(#f) 8 8))
(define freds-diagonal (make-shared-array fred (lambda (i) (list i i)) 8))
(array-set! freds-diagonal 'foo 3)
(array-ref fred 3 3)	; => foo
(define freds-center (make-shared-array fred (lambda (i j)
                                               (list (+ 3 i) (+ 3 j)))
                                        2 2))
(array-ref freds-center 0 0)	; => foo

(list->array 2 '#() '((1 2) (3 4)))	; => #2A((1 2) (3 4))
(list->array 0 '#() 3)
;Note vector returned, per SRFI 63	; => #(3)

(array->list (array '(2 3) 'ho 'ho 'ho 'ho 'oh 'oh))	; => ((ho ho ho) (ho oh oh))
(array->list (array 0 'ho))	; => ho

(vector->array (vector 1 2 3 4) '#() 2 2)	; => #2A((1 2) (3 4))
(vector->array '#(3) '#())	; => #(3)

(array->vector (array (make-array-shape 0 2 0 2) 1 2 3 4))	; => #(1 2 3 4)
(array->vector (array 0 'ho))	; => #(ho)

;; Assuming sparse-vectors works as advertised

(use sparse-vectors)

(define sparse-vector-empty-element-tag (gensym))

(define (sparse-vector-element? obj)
  (not (eq? sparse-vector-empty-element-tag obj)) )

(define (list->sparse-vector lst)
  (let ([sv (make-sparse-vector sparse-vector-empty-element-tag)])
    (do ([i 0 (add1 i)]
         [elms lst (cdr elms)])
        [(null? elms) sv]
      (and-let* ([elm (car elms)])
        (sparse-vector-set! sv i elm))) ) )

(define (sparse-vector-length sv)
  ; This is expensive
  (length (sparse-vector->list sv)) )

(define (a:sv #!optional value)
  (let ([sv (make-sparse-vector sparse-vector-empty-element-tag)])
    (when (sparse-vector-element? value)
      (sparse-vector-set! sv 0 value) )
    sv ) )

(array:storage-definition 'sparse-vector
  sparse-vector-element?
  (lambda (len) (make-sparse-vector sparse-vector-empty-element-tag))
  sparse-vector?
  (lambda (sv idx)
    (let ([obj (sparse-vector-ref sv idx)])
      (if (sparse-vector-element? obj)
          obj
          (error 'sparse-vector-ref "no such element" idx sv))))
  sparse-vector-set!
  sparse-vector-length
  sparse-vector->list
  list->sparse-vector
  ; Don't supply initial value, otherwise NOT SPARSE!
  (a:sv))

(define sva1 (make-array (a:sv) 2 2))
(array-strict? sva1)  ; => #t
(array->list sva1)    ; => ()
(array->vector sva1)  ; => #()
(array-empty? sva1)   ; => #t
(array-ref sva1 1 1)  ; => Error: (sparse-vector-ref) no such element:
                           3
                           #()
(array-set! sva1 'skidoo 1 1)
(array-ref sva1 1 1)  ; => skidoo
(array-empty? sva1)   ; => #f
(array->list sva1)    ; =? ((#f #f) (#f skidoo))
(array->vector sva1)  ; => #(#f #f #f skidoo)

;;
;; See "array-lib-test.scm" in the testbase tests repository for more examples.
;;

Author

Kon Lovett

Acknowledgments

Thanks to Ivan Shmakov and Terrence Brannon for exploring the corners and uncovering bugs.

Version

License

Copyright (c) 2006, 2007 Kon Lovett.  All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the Software),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ASIS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Copyright (C) 2001, 2003, 2005 Aubrey Jaffer

Permission to copy this software, to modify it, to redistribute it,
to distribute modified versions, and to use it for any purpose is
granted, subject to the following restrictions and understandings.

1. Any copy made of this software must include this copyright notice
in full.

2. I have made no warranty or representation that the operation of
this software will be error-free, and I am under no obligation to
provide any services, by way of maintenance, update, or otherwise.

3. In conjunction with products arising from the use of this
material, there shall be no use of my name in any advertising,
promotional, or sales literature without prior written consent in
each case.