   Guile Reference Manual Copyright (C) 1996 Free Software Foundation
Copyright (C) 1997 Free Software Foundation
Copyright (C) 2000 Free Software Foundation
Copyright (C) 2001 Free Software Foundation
Copyright (C) 2002 Free Software Foundation

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Free Software Foundation.

Records
=======

   A "record type" is a first class object representing a user-defined
data type.  A "record" is an instance of a record type.

 - Scheme Procedure: record? obj
     Return `#t' if OBJ is a record of any type and `#f' otherwise.

     Note that `record?' may be true of any Scheme value; there is no
     promise that records are disjoint with other Scheme types.

 - Scheme Procedure: make-record-type type-name field-names
     Return a "record-type descriptor", a value representing a new data
     type disjoint from all others.  The TYPE-NAME argument must be a
     string, but is only used for debugging purposes (such as the
     printed representation of a record of the new type).  The
     FIELD-NAMES argument is a list of symbols naming the "fields" of a
     record of the new type.  It is an error if the list contains any
     duplicates.  It is unspecified how record-type descriptors are
     represented.

 - Scheme Procedure: record-constructor rtd [field-names]
     Return a procedure for constructing new members of the type
     represented by RTD.  The returned procedure accepts exactly as
     many arguments as there are symbols in the given list,
     FIELD-NAMES; these are used, in order, as the initial values of
     those fields in a new record, which is returned by the constructor
     procedure.  The values of any fields not named in that list are
     unspecified.  The FIELD-NAMES argument defaults to the list of
     field names in the call to `make-record-type' that created the
     type represented by RTD; if the FIELD-NAMES argument is provided,
     it is an error if it contains any duplicates or any symbols not in
     the default list.

 - Scheme Procedure: record-predicate rtd
     Return a procedure for testing membership in the type represented
     by RTD.  The returned procedure accepts exactly one argument and
     returns a true value if the argument is a member of the indicated
     record type; it returns a false value otherwise.

 - Scheme Procedure: record-accessor rtd field-name
     Return a procedure for reading the value of a particular field of a
     member of the type represented by RTD.  The returned procedure
     accepts exactly one argument which must be a record of the
     appropriate type; it returns the current value of the field named
     by the symbol FIELD-NAME in that record.  The symbol FIELD-NAME
     must be a member of the list of field-names in the call to
     `make-record-type' that created the type represented by RTD.

 - Scheme Procedure: record-modifier rtd field-name
     Return a procedure for writing the value of a particular field of a
     member of the type represented by RTD.  The returned procedure
     accepts exactly two arguments: first, a record of the appropriate
     type, and second, an arbitrary Scheme value; it modifies the field
     named by the symbol FIELD-NAME in that record to contain the given
     value.  The returned value of the modifier procedure is
     unspecified.  The symbol FIELD-NAME must be a member of the list
     of field-names in the call to `make-record-type' that created the
     type represented by RTD.

 - Scheme Procedure: record-type-descriptor record
     Return a record-type descriptor representing the type of the given
     record.  That is, for example, if the returned descriptor were
     passed to `record-predicate', the resulting predicate would return
     a true value when passed the given record.  Note that it is not
     necessarily the case that the returned descriptor is the one that
     was passed to `record-constructor' in the call that created the
     constructor procedure that created the given record.

 - Scheme Procedure: record-type-name rtd
     Return the type-name associated with the type represented by rtd.
     The returned value is `eqv?' to the TYPE-NAME argument given in
     the call to `make-record-type' that created the type represented by
     RTD.

 - Scheme Procedure: record-type-fields rtd
     Return a list of the symbols naming the fields in members of the
     type represented by RTD.  The returned value is `equal?' to the
     field-names argument given in the call to `make-record-type' that
     created the type represented by RTD.

Structures
==========

   [FIXME: this is pasted in from Tom Lord's original guile.texi and
should be reviewed]

   A "structure type" is a first class user-defined data type.  A
"structure" is an instance of a structure type.  A structure type is
itself a structure.

   Structures are less abstract and more general than traditional
records.  In fact, in Guile Scheme, records are implemented using
structures.

Structure Concepts
------------------

   A structure object consists of a handle, structure data, and a
vtable.  The handle is a Scheme value which points to both the vtable
and the structure's data.  Structure data is a dynamically allocated
region of memory, private to the structure, divided up into typed
fields.  A vtable is another structure used to hold type-specific data.
Multiple structures can share a common vtable.

   Three concepts are key to understanding structures.

   * "layout specifications"

     Layout specifications determine how memory allocated to structures
     is divided up into fields.  Programmers must write a layout
     specification whenever a new type of structure is defined.

   * "structural accessors"

     Structure access is by field number.   There is only one set of
     accessors common to all structure objects.

   * "vtables"

     Vtables, themselves structures, are first class representations of
     disjoint sub-types of structures in general.   In most cases, when
     a new structure is created, programmers must specify a vtable for
     the new structure.   Each vtable has a field describing the layout
     of its instances.   Vtables can have additional, user-defined
     fields as well.

Structure Layout
----------------

   When a structure is created, a region of memory is allocated to hold
its state.  The "layout" of the structure's type determines how that
memory is divided into fields.

   Each field has a specified type.  There are only three types
allowed, each corresponding to a one letter code.  The allowed types
are:

   * 'u' - unprotected

     The field holds binary data that is not GC protected.

   * 'p' - protected

     The field holds a Scheme value and is GC protected.

   * 's' - self

     The field holds a Scheme value and is GC protected.  When a
     structure is created with this type of field, the field is
     initialized to refer to the structure's own handle.  This kind of
     field is mainly useful when mixing Scheme and C code in which the
     C code may need to compute a structure's handle given only the
     address of its malloc'd data.

   Each field also has an associated access protection.   There are only
three kinds of protection, each corresponding to a one letter code.
The allowed protections are:

   * 'w' - writable

     The field can be read and written.

   * 'r' - readable

     The field can be read, but not written.

   * 'o' - opaque

     The field can be neither read nor written.   This kind of
     protection is for fields useful only to built-in routines.

   A layout specification is described by stringing together pairs of
letters: one to specify a field type and one to specify a field
protection.    For example, a traditional cons pair type object could
be described as:

     ; cons pairs have two writable fields of Scheme data
     "pwpw"

   A pair object in which the first field is held constant could be:

     "prpw"

   Binary fields, (fields of type "u"), hold one "word" each.  The size
of a word is a machine dependent value defined to be equal to the value
of the C expression: `sizeof (long)'.

   The last field of a structure layout may specify a tail array.  A
tail array is indicated by capitalizing the field's protection code
('W', 'R' or 'O').   A tail-array field is replaced by a read-only
binary data field containing an array size.   The array size is
determined at the time the structure is created.  It is followed by a
corresponding number of fields of the type specified for the tail
array.   For example, a conventional Scheme vector can be described as:

     ; A vector is an arbitrary number of writable fields holding Scheme
     ; values:
     "pW"

   In the above example, field 0 contains the size of the vector and
fields beginning at 1 contain the vector elements.

   A kind of tagged vector (a constant tag followed by conventional
vector elements) might be:

     "prpW"

   Structure layouts are represented by specially interned symbols whose
name is a string of type and protection codes.  To create a new
structure layout, use this procedure:

 - Scheme Procedure: make-struct-layout fields
 - C Function: scm_make_struct_layout (fields)
     Return a new structure layout object.

     FIELDS must be a string made up of pairs of characters strung
     together.  The first character of each pair describes a field
     type, the second a field protection.  Allowed types are 'p' for
     GC-protected Scheme data, 'u' for unprotected binary data, and 's'
     for a field that points to the structure itself.    Allowed
     protections are 'w' for mutable fields, 'r' for read-only fields,
     and 'o' for opaque fields.  The last field protection
     specification may be capitalized to indicate that the field is a
     tail-array.

Structure Basics
----------------

   This section describes the basic procedures for creating and
accessing structures.

 - Scheme Procedure: make-struct vtable tail_array_size . init
 - C Function: scm_make_struct (vtable, tail_array_size, init)
     Create a new structure.

     TYPE must be a vtable structure (see Vtables).

     TAIL-ELTS must be a non-negative integer.  If the layout
     specification indicated by TYPE includes a tail-array, this is the
     number of elements allocated to that array.

     The INIT1, ... are optional arguments describing how successive
     fields of the structure should be initialized.  Only fields with
     protection 'r' or 'w' can be initialized, except for fields of
     type 's', which are automatically initialized to point to the new
     structure itself; fields with protection 'o' can not be
     initialized by Scheme programs.

     If fewer optional arguments than initializable fields are supplied,
     fields of type 'p' get default value #f while fields of type 'u'
     are initialized to 0.

     Structs are currently the basic representation for record-like data
     structures in Guile.  The plan is to eventually replace them with a
     new representation which will at the same time be easier to use and
     more powerful.

     For more information, see the documentation for
     `make-vtable-vtable'.

 - Scheme Procedure: struct? x
 - C Function: scm_struct_p (x)
     Return `#t' iff X is a structure object, else `#f'.

 - Scheme Procedure: struct-ref handle pos
 - Scheme Procedure: struct-set! struct n value
 - C Function: scm_struct_ref (handle, pos)
 - C Function: scm_struct_set_x (struct, n, value)
     Access (or modify) the Nth field of STRUCT.

     If the field is of type 'p', then it can be set to an arbitrary
     value.

     If the field is of type 'u', then it can only be set to a
     non-negative integer value small enough to fit in one machine word.

Vtables
-------

   Vtables are structures that are used to represent structure types.
Each vtable contains a layout specification in field
`vtable-index-layout' - instances of the type are laid out according to
that specification.  Vtables contain additional fields which are used
only internally to libguile.  The variable `vtable-offset-user' is
bound to a field number.  Vtable fields at that position or greater are
user definable.

 - Scheme Procedure: struct-vtable handle
 - C Function: scm_struct_vtable (handle)
     Return the vtable structure that describes the type of STRUCT.

 - Scheme Procedure: struct-vtable? x
 - C Function: scm_struct_vtable_p (x)
     Return `#t' iff X is a vtable structure.

   If you have a vtable structure, `V', you can create an instance of
the type it describes by using `(make-struct V ...)'.  But where does
`V' itself come from?  One possibility is that `V' is an instance of a
user-defined vtable type, `V'', so that `V' is created by using
`(make-struct V' ...)'.  Another possibility is that `V' is an instance
of the type it itself describes.  Vtable structures of the second sort
are created by this procedure:

 - Scheme Procedure: make-vtable-vtable user_fields tail_array_size .
          init
 - C Function: scm_make_vtable_vtable (user_fields, tail_array_size,
          init)
     Return a new, self-describing vtable structure.

     USER-FIELDS is a string describing user defined fields of the
     vtable beginning at index `vtable-offset-user' (see
     `make-struct-layout').

     TAIL-SIZE specifies the size of the tail-array (if any) of this
     vtable.

     INIT1, ... are the optional initializers for the fields of the
     vtable.

     Vtables have one initializable system field--the struct printer.
     This field comes before the user fields in the initializers passed
     to `make-vtable-vtable' and `make-struct', and thus works as a
     third optional argument to `make-vtable-vtable' and a fourth to
     `make-struct' when creating vtables:

     If the value is a procedure, it will be called instead of the
     standard printer whenever a struct described by this vtable is
     printed.  The procedure will be called with arguments STRUCT and
     PORT.

     The structure of a struct is described by a vtable, so the vtable
     is in essence the type of the struct.  The vtable is itself a
     struct with a vtable.  This could go on forever if it weren't for
     the vtable-vtables which are self-describing vtables, and thus
     terminate the chain.

     There are several potential ways of using structs, but the standard
     one is to use three kinds of structs, together building up a type
     sub-system: one vtable-vtable working as the root and one or
     several "types", each with a set of "instances".  (The
     vtable-vtable should be compared to the class <class> which is the
     class of itself.)

          (define ball-root (make-vtable-vtable "pr" 0))

          (define (make-ball-type ball-color)
            (make-struct ball-root 0
          	       (make-struct-layout "pw")
                         (lambda (ball port)
                           (format port "#<a ~A ball owned by ~A>"
                                   (color ball)
                                   (owner ball)))
                         ball-color))
          (define (color ball) (struct-ref (struct-vtable ball) vtable-offset-user))
          (define (owner ball) (struct-ref ball 0))

          (define red (make-ball-type 'red))
          (define green (make-ball-type 'green))

          (define (make-ball type owner) (make-struct type 0 owner))

          (define ball (make-ball green 'Nisse))
          ball => #<a green ball owned by Nisse>

 - Scheme Procedure: struct-vtable-name vtable
 - C Function: scm_struct_vtable_name (vtable)
     Return the name of the vtable VTABLE.

 - Scheme Procedure: set-struct-vtable-name! vtable name
 - C Function: scm_set_struct_vtable_name_x (vtable, name)
     Set the name of the vtable VTABLE to NAME.

 - Scheme Procedure: struct-vtable-tag handle
 - C Function: scm_struct_vtable_tag (handle)
     Return the vtable tag of the structure HANDLE.

Arrays
======

Conventional Arrays
-------------------

   "Conventional arrays" are a collection of cells organized into an
arbitrary number of dimensions.  Each cell can hold any kind of Scheme
value and can be accessed in constant time by supplying an index for
each dimension.  This contrasts with uniform arrays, which use memory
more efficiently but can hold data of only a single type, and lists
where inserting and deleting cells is more efficient, but more time is
usually required to access a particular cell.

   A conventional array is displayed as `#' followed by the "rank"
(number of dimensions) followed by the cells, organized into dimensions
using parentheses.  The nesting depth of the parentheses is equal to
the rank.

   When an array is created, the number of dimensions and range of each
dimension must be specified, e.g., to create a 2x3 array with a
zero-based index:

     (make-array 'ho 2 3) =>
     #2((ho ho ho) (ho ho ho))

   The range of each dimension can also be given explicitly, e.g.,
another way to create the same array:

     (make-array 'ho '(0 1) '(0 2)) =>
     #2((ho ho ho) (ho ho ho))

   A conventional array with one dimension based at zero is identical to
a vector:

     (make-array 'ho 3) =>
     #(ho ho ho)

   The following procedures can be used with conventional arrays (or
vectors).

 - Scheme Procedure: array? v [prot]
 - C Function: scm_array_p (v, prot)
     Return `#t' if the OBJ is an array, and `#f' if not.  The
     PROTOTYPE argument is used with uniform arrays and is described
     elsewhere.

 - Scheme Procedure: make-array initial-value bound1 bound2 ...
     Create and return an array that has as many dimensions as there are
     BOUNDs and fill it with INITIAL-VALUE.  Each BOUND may be a
     positive non-zero integer N, in which case the index for that
     dimension can range from 0 through N-1; or an explicit index range
     specifier in the form `(LOWER UPPER)', where both LOWER and UPPER
     are integers, possibly less than zero, and possibly the same
     number (however, LOWER cannot be greater than UPPER).

 - Scheme Procedure: uniform-vector-ref v args
 - Scheme Procedure: array-ref v . args
 - C Function: scm_uniform_vector_ref (v, args)
     Return the element at the `(index1, index2)' element in ARRAY.

 - Scheme Procedure: array-in-bounds? v . args
 - C Function: scm_array_in_bounds_p (v, args)
     Return `#t' if its arguments would be acceptable to `array-ref'.

 - Scheme Procedure: array-set! v obj . args
 - Scheme Procedure: uniform-array-set1! v obj args
 - C Function: scm_array_set_x (v, obj, args)
     Set the element at the `(index1, index2)' element in ARRAY to
     NEW-VALUE.  The value returned by array-set! is unspecified.

 - Scheme Procedure: make-shared-array oldra mapfunc . dims
 - C Function: scm_make_shared_array (oldra, mapfunc, dims)
     `make-shared-array' can be used to create shared subarrays of other
     arrays.  The MAPPER is a function that translates coordinates in
     the new array into coordinates in the old array.  A MAPPER must be
     linear, and its range must stay within the bounds of the old
     array, but it can be otherwise arbitrary.  A simple example:
          (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

 - Scheme Procedure: shared-array-increments ra
 - C Function: scm_shared_array_increments (ra)
     For each dimension, return the distance between elements in the
     root vector.

 - Scheme Procedure: shared-array-offset ra
 - C Function: scm_shared_array_offset (ra)
     Return the root vector index of the first element in the array.

 - Scheme Procedure: shared-array-root ra
 - C Function: scm_shared_array_root (ra)
     Return the root vector of a shared array.

 - Scheme Procedure: transpose-array ra . args
 - C Function: scm_transpose_array (ra, args)
     Return an array sharing contents with ARRAY, but with dimensions
     arranged in a different order.  There must be one DIM argument for
     each dimension of ARRAY.  DIM0, DIM1, ... should be integers
     between 0 and the rank of the array to be returned.  Each integer
     in that range must appear at least once in the argument list.

     The values of DIM0, DIM1, ... correspond to dimensions in the
     array to be returned, their positions in the argument list to
     dimensions of ARRAY.  Several DIMs may have the same value, in
     which case the returned array will have smaller rank than ARRAY.

          (transpose-array '#2((a b) (c d)) 1 0) => #2((a c) (b d))
          (transpose-array '#2((a b) (c d)) 0 0) => #1(a d)
          (transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) =>
                          #2((a 4) (b 5) (c 6))

 - Scheme Procedure: enclose-array ra . axes
 - C Function: scm_enclose_array (ra, axes)
     DIM0, DIM1 ... should be nonnegative integers less than the rank
     of ARRAY.  ENCLOSE-ARRAY returns an array resembling an array of
     shared arrays.  The dimensions of each shared array are the same
     as the DIMth dimensions of the original array, the dimensions of
     the outer array are the same as those of the original array that
     did not match a DIM.

     An enclosed array is not a general Scheme array.  Its elements may
     not be set using `array-set!'.  Two references to the same element
     of an enclosed array will be `equal?' but will not in general be
     `eq?'.  The value returned by ARRAY-PROTOTYPE when given an
     enclosed array is unspecified.

     examples:
          (enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) =>
             #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>

          (enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) =>
             #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>

 - Scheme Procedure: array-shape array
     Return a list of inclusive bounds of integers.
          (array-shape (make-array 'foo '(-1 3) 5)) => ((-1 3) (0 4))

 - Scheme Procedure: array-dimensions ra
 - C Function: scm_array_dimensions (ra)
     `Array-dimensions' is similar to `array-shape' but replaces
     elements with a `0' minimum with one greater than the maximum. So:
          (array-dimensions (make-array 'foo '(-1 3) 5)) => ((-1 3) 5)

 - Scheme Procedure: array-rank ra
 - C Function: scm_array_rank (ra)
     Return the number of dimensions of OBJ.  If OBJ is not an array,
     `0' is returned.

 - Scheme Procedure: array->list v
 - C Function: scm_array_to_list (v)
     Return a list consisting of all the elements, in order, of ARRAY.

 - Scheme Procedure: array-copy! src dst
 - Scheme Procedure: array-copy-in-order! src dst
 - C Function: scm_array_copy_x (src, dst)
     Copy every element from vector or array SOURCE to the
     corresponding element of DESTINATION.  DESTINATION must have the
     same rank as SOURCE, and be at least as large in each dimension.
     The order is unspecified.

 - Scheme Procedure: array-fill! ra fill
 - C Function: scm_array_fill_x (ra, fill)
     Store FILL in every element of ARRAY.  The value returned is
     unspecified.

 - Scheme Procedure: array-equal? ra0 ra1
     Return `#t' iff all arguments are arrays with the same shape, the
     same type, and have corresponding elements which are either
     `equal?'  or `array-equal?'.  This function differs from `equal?'
     in that a one dimensional shared array may be ARRAY-EQUAL? but not
     EQUAL? to a vector or uniform vector.

 - Scheme Procedure: array-contents array [strict]
 - C Function: scm_array_contents (array, strict)
     If ARRAY may be "unrolled" into a one dimensional shared array
     without changing their order (last subscript changing fastest),
     then `array-contents' returns that shared array, otherwise it
     returns `#f'.  All arrays made by MAKE-ARRAY and
     MAKE-UNIFORM-ARRAY may be unrolled, some arrays made by
     MAKE-SHARED-ARRAY may not be.

     If the optional argument STRICT is provided, a shared array will
     be returned only if its elements are stored internally contiguous
     in memory.

Array Mapping
-------------

 - Scheme Procedure: array-map! ra0 proc . lra
 - Scheme Procedure: array-map-in-order! ra0 proc . lra
 - C Function: scm_array_map_x (ra0, proc, lra)
     ARRAY1, ... must have the same number of dimensions as ARRAY0 and
     have a range for each index which includes the range for the
     corresponding index in ARRAY0.  PROC is applied to each tuple of
     elements of ARRAY1 ... and the result is stored as the
     corresponding element in ARRAY0.  The value returned is
     unspecified.  The order of application is unspecified.

 - Scheme Procedure: array-for-each proc ra0 . lra
 - C Function: scm_array_for_each (proc, ra0, lra)
     Apply PROC to each tuple of elements of ARRAY0 ...  in row-major
     order.  The value returned is unspecified.

 - Scheme Procedure: array-index-map! ra proc
 - C Function: scm_array_index_map_x (ra, proc)
     Apply PROC to the indices of each element of ARRAY in turn,
     storing the result in the corresponding element.  The value
     returned and the order of application are unspecified.

     One can implement ARRAY-INDEXES as
          (define (array-indexes array)
              (let ((ra (apply make-array #f (array-shape array))))
                (array-index-map! ra (lambda x x))
                ra))
     Another example:
          (define (apl:index-generator n)
              (let ((v (make-uniform-vector n 1)))
                (array-index-map! v (lambda (i) i))
                v))

Uniform Arrays
--------------

"Uniform arrays" have elements all of the same type and occupy less
storage than conventional arrays.  Uniform arrays with a single
zero-based dimension are also known as "uniform vectors".  The
procedures in this section can also be used on conventional arrays,
vectors, bit-vectors and strings.

When creating a uniform array, the type of data to be stored is
indicated with a PROTOTYPE argument.  The following table lists the
types available and example prototypes:

     prototype           type                       printing character

     #t             boolean (bit-vector)                    b
     #\a            char (string)                           a
     #\nul          byte (integer)                          y
     's             short (integer)                         h
     1              unsigned long (integer)                 u
     -1             signed long (integer)                   e
     'l             signed long long (integer)              l
     1.0            float (single precision)                s
     1/3            double (double precision float)         i
     0+i            complex (double precision)              c
     ()             conventional vector

Unshared uniform arrays of characters with a single zero-based dimension
are identical to strings:

     (make-uniform-array #\a 3) =>
     "aaa"

Unshared uniform arrays of booleans with a single zero-based dimension
are identical to bit-vectors.

     (make-uniform-array #t 3) =>
     #*111

Other uniform vectors are written in a form similar to that of vectors,
except that a single character from the above table is put between `#'
and `('.  For example, a uniform vector of signed long integers is
displayed in the form `'#e(3 5 9)'.

 - Scheme Procedure: array? v [prot]
     Return `#t' if the OBJ is an array, and `#f' if not.

     The PROTOTYPE argument is used with uniform arrays and is described
     elsewhere.

 - Scheme Procedure: make-uniform-array prototype bound1 bound2 ...
     Create and return a uniform array of type corresponding to
     PROTOTYPE that has as many dimensions as there are BOUNDs and fill
     it with PROTOTYPE.

 - Scheme Procedure: array-prototype ra
 - C Function: scm_array_prototype (ra)
     Return an object that would produce an array of the same type as
     ARRAY, if used as the PROTOTYPE for `make-uniform-array'.

 - Scheme Procedure: list->uniform-array ndim prot lst
 - Scheme Procedure: list->uniform-vector prot lst
 - C Function: scm_list_to_uniform_array (ndim, prot, lst)
     Return a uniform array of the type indicated by prototype PROT
     with elements the same as those of LST.  Elements must be of the
     appropriate type, no coercions are done.

 - Scheme Procedure: uniform-vector-fill! uve fill
     Store FILL in every element of UVE.  The value returned is
     unspecified.

 - Scheme Procedure: uniform-vector-length v
 - C Function: scm_uniform_vector_length (v)
     Return the number of elements in UVE.

 - Scheme Procedure: dimensions->uniform-array dims prot [fill]
 - Scheme Procedure: make-uniform-vector length prototype [fill]
 - C Function: scm_dimensions_to_uniform_array (dims, prot, fill)
     Create and return a uniform array or vector of type corresponding
     to PROTOTYPE with dimensions DIMS or length LENGTH.  If FILL is
     supplied, it's used to fill the array, otherwise PROTOTYPE is used.

 - Scheme Procedure: uniform-array-read! ra [port_or_fd [start [end]]]
 - Scheme Procedure: uniform-vector-read! uve [port-or-fdes] [start]
          [end]
 - C Function: scm_uniform_array_read_x (ra, port_or_fd, start, end)
     Attempt to read all elements of URA, in lexicographic order, as
     binary objects from PORT-OR-FDES.  If an end of file is
     encountered, the objects up to that point are put into URA
     (starting at the beginning) and the remainder of the array is
     unchanged.

     The optional arguments START and END allow a specified region of a
     vector (or linearized array) to be read, leaving the remainder of
     the vector unchanged.

     `uniform-array-read!' returns the number of objects read.
     PORT-OR-FDES may be omitted, in which case it defaults to the value
     returned by `(current-input-port)'.

 - Scheme Procedure: uniform-array-write v [port_or_fd [start [end]]]
 - Scheme Procedure: uniform-vector-write uve [port-or-fdes] [start]
          [end]
 - C Function: scm_uniform_array_write (v, port_or_fd, start, end)
     Writes all elements of URA as binary objects to PORT-OR-FDES.

     The optional arguments START and END allow a specified region of a
     vector (or linearized array) to be written.

     The number of objects actually written is returned.  PORT-OR-FDES
     may be omitted, in which case it defaults to the value returned by
     `(current-output-port)'.

Bit Vectors
-----------

Bit vectors are a specific type of uniform array: an array of booleans
with a single zero-based index.

They are displayed as a sequence of `0's and `1's prefixed by `#*',
e.g.,

     (make-uniform-vector 8 #t #f) =>
     #*00000000

     #b(#t #f #t) =>
     #*101

 - Scheme Procedure: bit-count b bitvector
 - C Function: scm_bit_count (b, bitvector)
     Return the number of occurrences of the boolean B in BITVECTOR.

 - Scheme Procedure: bit-position item v k
 - C Function: scm_bit_position (item, v, k)
     Return the minimum index of an occurrence of BOOL in BV which is
     at least K.  If no BOOL occurs within the specified range `#f' is
     returned.

 - Scheme Procedure: bit-invert! v
 - C Function: scm_bit_invert_x (v)
     Modify BV by replacing each element with its negation.

 - Scheme Procedure: bit-set*! v kv obj
 - C Function: scm_bit_set_star_x (v, kv, obj)
     If uve is a bit-vector BV and uve must be of the same length.  If
     BOOL is `#t', uve is OR'ed into BV; If BOOL is `#f', the inversion
     of uve is AND'ed into BV.

     If uve is a unsigned long integer vector all the elements of uve
     must be between 0 and the `length' of BV.  The bits of BV
     corresponding to the indexes in uve are set to BOOL.  The return
     value is unspecified.

 - Scheme Procedure: bit-count* v kv obj
 - C Function: scm_bit_count_star (v, kv, obj)
     Return
          (bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).
     BV is not modified.

Association Lists and Hash Tables
=================================

   This chapter discusses dictionary objects: data structures that are
useful for organizing and indexing large bodies of information.

Dictionary Types
----------------

   A "dictionary" object is a data structure used to index information
in a user-defined way.  In standard Scheme, the main aggregate data
types are lists and vectors.  Lists are not really indexed at all, and
vectors are indexed only by number (e.g. `(vector-ref foo 5)').  Often
you will find it useful to index your data on some other type; for
example, in a library catalog you might want to look up a book by the
name of its author.  Dictionaries are used to help you organize
information in such a way.

   An "association list" (or "alist" for short) is a list of key-value
pairs.  Each pair represents a single quantity or object; the `car' of
the pair is a key which is used to identify the object, and the `cdr'
is the object's value.

   A "hash table" also permits you to index objects with arbitrary
keys, but in a way that makes looking up any one object extremely fast.
A well-designed hash system makes hash table lookups almost as fast as
conventional array or vector references.

   Alists are popular among Lisp programmers because they use only the
language's primitive operations (lists, "car", "cdr" and the equality
primitives).  No changes to the language core are necessary.
Therefore, with Scheme's built-in list manipulation facilities, it is
very convenient to handle data stored in an association list.  Also,
alists are highly portable and can be easily implemented on even the
most minimal Lisp systems.

   However, alists are inefficient, especially for storing large
quantities of data.  Because we want Guile to be useful for large
software systems as well as small ones, Guile provides a rich set of
tools for using either association lists or hash tables.

Association Lists
-----------------

   An association list is a conventional data structure that is often
used to implement simple key-value databases.  It consists of a list of
entries in which each entry is a pair.  The "key" of each entry is the
`car' of the pair and the "value" of each entry is the `cdr'.

     ASSOCIATION LIST ::=  '( (KEY1 . VALUE1)
                              (KEY2 . VALUE2)
                              (KEY3 . VALUE3)
                              ...
                            )

Association lists are also known, for short, as "alists".

   The structure of an association list is just one example of the
infinite number of possible structures that can be built using pairs
and lists.  As such, the keys and values in an association list can be
manipulated using the general list structure procedures `cons', `car',
`cdr', `set-car!', `set-cdr!' and so on.  However, because association
lists are so useful, Guile also provides specific procedures for
manipulating them.

Alist Key Equality
..................

   All of Guile's dedicated association list procedures, apart from
`acons', come in three flavours, depending on the level of equality
that is required to decide whether an existing key in the association
list is the same as the key that the procedure call uses to identify the
required entry.

   * Procedures with "assq" in their name use `eq?' to determine key
     equality.

   * Procedures with "assv" in their name use `eqv?' to determine key
     equality.

   * Procedures with "assoc" in their name use `equal?' to determine
     key equality.

   `acons' is an exception because it is used to build association
lists which do not require their entries' keys to be unique.

Adding or Setting Alist Entries
...............................

   `acons' adds a new entry to an association list and returns the
combined association list.  The combined alist is formed by consing the
new entry onto the head of the alist specified in the `acons' procedure
call.  So the specified alist is not modified, but its contents become
shared with the tail of the combined alist that `acons' returns.

   In the most common usage of `acons', a variable holding the original
association list is updated with the combined alist:

     (set! address-list (acons name address address-list))

   In such cases, it doesn't matter that the old and new values of
`address-list' share some of their contents, since the old value is
usually no longer independently accessible.

   Note that `acons' adds the specified new entry regardless of whether
the alist may already contain entries with keys that are, in some
sense, the same as that of the new entry.  Thus `acons' is ideal for
building alists where there is no concept of key uniqueness.

     (set! task-list (acons 3 "pay gas bill" '()))
     task-list
     =>
     ((3 . "pay gas bill"))

     (set! task-list (acons 3 "tidy bedroom" task-list))
     task-list
     =>
     ((3 . "tidy bedroom") (3 . "pay gas bill"))

   `assq-set!', `assv-set!' and `assoc-set!' are used to add or replace
an entry in an association list where there _is_ a concept of key
uniqueness.  If the specified association list already contains an
entry whose key is the same as that specified in the procedure call,
the existing entry is replaced by the new one.  Otherwise, the new
entry is consed onto the head of the old association list to create the
combined alist.  In all cases, these procedures return the combined
alist.

   `assq-set!' and friends _may_ destructively modify the structure of
the old association list in such a way that an existing variable is
correctly updated without having to `set!' it to the value returned:

     address-list
     =>
     (("mary" . "34 Elm Road") ("james" . "16 Bow Street"))

     (assoc-set! address-list "james" "1a London Road")
     =>
     (("mary" . "34 Elm Road") ("james" . "1a London Road"))

     address-list
     =>
     (("mary" . "34 Elm Road") ("james" . "1a London Road"))

   Or they may not:

     (assoc-set! address-list "bob" "11 Newington Avenue")
     =>
     (("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
      ("james" . "1a London Road"))

     address-list
     =>
     (("mary" . "34 Elm Road") ("james" . "1a London Road"))

   The only safe way to update an association list variable when adding
or replacing an entry like this is to `set!' the variable to the
returned value:

     (set! address-list
           (assoc-set! address-list "bob" "11 Newington Avenue"))
     address-list
     =>
     (("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
      ("james" . "1a London Road"))

   Because of this slight inconvenience, you may find it more
convenient to use hash tables to store dictionary data.  If your
application will not be modifying the contents of an alist very often,
this may not make much difference to you.

   If you need to keep the old value of an association list in a form
independent from the list that results from modification by `acons',
`assq-set!', `assv-set!' or `assoc-set!', use `list-copy' to copy the
old association list before modifying it.

 - Scheme Procedure: acons key value alist
 - C Function: scm_acons (key, value, alist)
     Add a new key-value pair to ALIST.  A new pair is created whose
     car is KEY and whose cdr is VALUE, and the pair is consed onto
     ALIST, and the new list is returned.  This function is _not_
     destructive; ALIST is not modified.

 - Scheme Procedure: assq-set! alist key val
 - Scheme Procedure: assv-set! alist key value
 - Scheme Procedure: assoc-set! alist key value
 - C Function: scm_assq_set_x (alist, key, val)
 - C Function: scm_assv_set_x (alist, key, val)
 - C Function: scm_assoc_set_x (alist, key, val)
     Reassociate KEY in ALIST with VALUE: find any existing ALIST entry
     for KEY and associate it with the new VALUE.  If ALIST does not
     contain an entry for KEY, add a new one.  Return the (possibly
     new) alist.

     These functions do not attempt to verify the structure of ALIST,
     and so may cause unusual results if passed an object that is not an
     association list.

Retrieving Alist Entries
........................

   `assq', `assv' and `assoc' take an alist and a key as arguments and
return the entry for that key if an entry exists, or `#f' if there is
no entry for that key.  Note that, in the cases where an entry exists,
these procedures return the complete entry, that is `(KEY . VALUE)',
not just the value.

 - Scheme Procedure: assq key alist
 - Scheme Procedure: assv key alist
 - Scheme Procedure: assoc key alist
 - C Function: scm_assq (key, alist)
 - C Function: scm_assv (key, alist)
 - C Function: scm_assoc (key, alist)
     Fetch the entry in ALIST that is associated with KEY.  To decide
     whether the argument KEY matches a particular entry in ALIST,
     `assq' compares keys with `eq?', `assv' uses `eqv?' and `assoc'
     uses `equal?'.  If KEY cannot be found in ALIST (according to
     whichever equality predicate is in use), then return `#f'.  These
     functions return the entire alist entry found (i.e. both the key
     and the value).

   `assq-ref', `assv-ref' and `assoc-ref', on the other hand, take an
alist and a key and return _just the value_ for that key, if an entry
exists.  If there is no entry for the specified key, these procedures
return `#f'.

   This creates an ambiguity: if the return value is `#f', it means
either that there is no entry with the specified key, or that there
_is_ an entry for the specified key, with value `#f'.  Consequently,
`assq-ref' and friends should only be used where it is known that an
entry exists, or where the ambiguity doesn't matter for some other
reason.

 - Scheme Procedure: assq-ref alist key
 - Scheme Procedure: assv-ref alist key
 - Scheme Procedure: assoc-ref alist key
 - C Function: scm_assq_ref (alist, key)
 - C Function: scm_assv_ref (alist, key)
 - C Function: scm_assoc_ref (alist, key)
     Like `assq', `assv' and `assoc', except that only the value
     associated with KEY in ALIST is returned.  These functions are
     equivalent to

          (let ((ent (ASSOCIATOR KEY ALIST)))
            (and ent (cdr ent)))

     where ASSOCIATOR is one of `assq', `assv' or `assoc'.

Removing Alist Entries
......................

   To remove the element from an association list whose key matches a
specified key, use `assq-remove!', `assv-remove!' or `assoc-remove!'
(depending, as usual, on the level of equality required between the key
that you specify and the keys in the association list).

   As with `assq-set!' and friends, the specified alist may or may not
be modified destructively, and the only safe way to update a variable
containing the alist is to `set!' it to the value that `assq-remove!'
and friends return.

     address-list
     =>
     (("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
      ("james" . "1a London Road"))

     (set! address-list (assoc-remove! address-list "mary"))
     address-list
     =>
     (("bob" . "11 Newington Avenue") ("james" . "1a London Road"))

   Note that, when `assq/v/oc-remove!' is used to modify an association
list that has been constructed only using the corresponding
`assq/v/oc-set!', there can be at most one matching entry in the alist,
so the question of multiple entries being removed in one go does not
arise.  If `assq/v/oc-remove!' is applied to an association list that
has been constructed using `acons', or an `assq/v/oc-set!' with a
different level of equality, or any mixture of these, it removes only
the first matching entry from the alist, even if the alist might
contain further matching entries.  For example:

     (define address-list '())
     (set! address-list (assq-set! address-list "mary" "11 Elm Street"))
     (set! address-list (assq-set! address-list "mary" "57 Pine Drive"))
     address-list
     =>
     (("mary" . "57 Pine Drive") ("mary" . "11 Elm Street"))

     (set! address-list (assoc-remove! address-list "mary"))
     address-list
     =>
     (("mary" . "11 Elm Street"))

   In this example, the two instances of the string "mary" are not the
same when compared using `eq?', so the two `assq-set!' calls add two
distinct entries to `address-list'.  When compared using `equal?', both
"mary"s in `address-list' are the same as the "mary" in the
`assoc-remove!' call, but `assoc-remove!' stops after removing the
first matching entry that it finds, and so one of the "mary" entries is
left in place.

 - Scheme Procedure: assq-remove! alist key
 - Scheme Procedure: assv-remove! alist key
 - Scheme Procedure: assoc-remove! alist key
 - C Function: scm_assq_remove_x (alist, key)
 - C Function: scm_assv_remove_x (alist, key)
 - C Function: scm_assoc_remove_x (alist, key)
     Delete the first entry in ALIST associated with KEY, and return
     the resulting alist.

Sloppy Alist Functions
......................

   `sloppy-assq', `sloppy-assv' and `sloppy-assoc' behave like the
corresponding non-`sloppy-' procedures, except that they return `#f'
when the specified association list is not well-formed, where the
non-`sloppy-' versions would signal an error.

   Specifically, there are two conditions for which the non-`sloppy-'
procedures signal an error, which the `sloppy-' procedures handle
instead by returning `#f'.  Firstly, if the specified alist as a whole
is not a proper list:

     (assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
     =>
     ERROR: In procedure assoc in expression (assoc "mary" (quote #)):
     ERROR: Wrong type argument in position 2 (expecting NULLP): "open sesame"
     ABORT: (wrong-type-arg)

     (sloppy-assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
     =>
     #f

Secondly, if one of the entries in the specified alist is not a pair:

     (assoc 2 '((1 . 1) 2 (3 . 9)))
     =>
     ERROR: In procedure assoc in expression (assoc 2 (quote #)):
     ERROR: Wrong type argument in position 2 (expecting CONSP): 2
     ABORT: (wrong-type-arg)

     (sloppy-assoc 2 '((1 . 1) 2 (3 . 9)))
     =>
     #f

   Unless you are explicitly working with badly formed association
lists, it is much safer to use the non-`sloppy-' procedures, because
they help to highlight coding and data errors that the `sloppy-'
versions would silently cover up.

 - Scheme Procedure: sloppy-assq key alist
 - C Function: scm_sloppy_assq (key, alist)
     Behaves like `assq' but does not do any error checking.
     Recommended only for use in Guile internals.

 - Scheme Procedure: sloppy-assv key alist
 - C Function: scm_sloppy_assv (key, alist)
     Behaves like `assv' but does not do any error checking.
     Recommended only for use in Guile internals.

 - Scheme Procedure: sloppy-assoc key alist
 - C Function: scm_sloppy_assoc (key, alist)
     Behaves like `assoc' but does not do any error checking.
     Recommended only for use in Guile internals.