Changes from arch/CVS synchronization
[bpt/guile.git] / doc / ref / api-compound.texi
index f117e1c..c00f3e9 100644 (file)
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
-@c Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004
+@c Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -22,9 +22,12 @@ values can be looked up within them.
 * Pairs::                       Scheme's basic building block.
 * Lists::                       Special list functions supported by Guile.
 * Vectors::                     One-dimensional arrays of Scheme objects.
+* Uniform Numeric Vectors::     Vectors with elements of a single numeric type.
+* Bit Vectors::                 Vectors of bits.
+* Generalized Vectors::         Treating all vector-like things uniformly.
+* Arrays::                      Matrices, etc.
 * Records::                     
 * Structures::                  
-* Arrays::                      Arrays of values.
 * Dictionary Types::            About dictionary types in general.
 * Association Lists::           List-based dictionaries.
 * Hash Tables::                 Table-based dictionaries.
@@ -60,8 +63,8 @@ parser would not be able to figure out where to split the tokens.
 
 But beware, if you want to try out these examples, you have to
 @dfn{quote} the expressions.  More information about quotation is
-available in the section (REFFIXME).  The correct way to try these
-examples is as follows.
+available in the section @ref{Expression Syntax}.  The correct way
+to try these examples is as follows.
 
 @lisp
 '(1 . 2)
@@ -93,25 +96,93 @@ Return @code{#t} if @var{x} is a pair; otherwise return
 @code{#f}.
 @end deffn
 
+@deftypefn {C Function} int scm_is_pair (SCM x)
+Return 1 when @var{x} is a pair; otherwise return 0.
+@end deftypefn
+
 The two parts of a pair are traditionally called @dfn{car} and
 @dfn{cdr}.  They can be retrieved with procedures of the same name
 (@code{car} and @code{cdr}), and can be modified with the procedures
 @code{set-car!} and @code{set-cdr!}.  Since a very common operation in
-Scheme programs is to access the car of a pair, or the car of the cdr of
-a pair, etc., the procedures called @code{caar}, @code{cadr} and so on
-are also predefined.
+Scheme programs is to access the car of a car of a pair, or the car of
+the cdr of a pair, etc., the procedures called @code{caar},
+@code{cadr} and so on are also predefined.
 
 @rnindex car
 @rnindex cdr
 @deffn {Scheme Procedure} car pair
 @deffnx {Scheme Procedure} cdr pair
+@deffnx {C Function} scm_car (pair)
+@deffnx {C Function} scm_cdr (pair)
 Return the car or the cdr of @var{pair}, respectively.
 @end deffn
 
-@deffn {Scheme Procedure} caar pair
-@deffnx {Scheme Procedure} cadr pair @dots{}
-@deffnx {Scheme Procedure} cdddar pair
+@deftypefn  {C Macro} SCM SCM_CAR (SCM pair)
+@deftypefnx {C Macro} SCM SCM_CDR (SCM pair)
+These two macros are the fastest way to access the car or cdr of a
+pair; they can be thought of as compiling into a single memory
+reference.
+
+These macros do no checking at all.  The argument @var{pair} must be a
+valid pair.
+@end deftypefn
+
+@deffn  {Scheme Procedure} cddr pair
+@deffnx {Scheme Procedure} cdar pair
+@deffnx {Scheme Procedure} cadr pair
+@deffnx {Scheme Procedure} caar pair
+@deffnx {Scheme Procedure} cdddr pair
+@deffnx {Scheme Procedure} cddar pair
+@deffnx {Scheme Procedure} cdadr pair
+@deffnx {Scheme Procedure} cdaar pair
+@deffnx {Scheme Procedure} caddr pair
+@deffnx {Scheme Procedure} cadar pair
+@deffnx {Scheme Procedure} caadr pair
+@deffnx {Scheme Procedure} caaar pair
 @deffnx {Scheme Procedure} cddddr pair
+@deffnx {Scheme Procedure} cdddar pair
+@deffnx {Scheme Procedure} cddadr pair
+@deffnx {Scheme Procedure} cddaar pair
+@deffnx {Scheme Procedure} cdaddr pair
+@deffnx {Scheme Procedure} cdadar pair
+@deffnx {Scheme Procedure} cdaadr pair
+@deffnx {Scheme Procedure} cdaaar pair
+@deffnx {Scheme Procedure} cadddr pair
+@deffnx {Scheme Procedure} caddar pair
+@deffnx {Scheme Procedure} cadadr pair
+@deffnx {Scheme Procedure} cadaar pair
+@deffnx {Scheme Procedure} caaddr pair
+@deffnx {Scheme Procedure} caadar pair
+@deffnx {Scheme Procedure} caaadr pair
+@deffnx {Scheme Procedure} caaaar pair
+@deffnx {C Function} scm_cddr (pair)
+@deffnx {C Function} scm_cdar (pair)
+@deffnx {C Function} scm_cadr (pair)
+@deffnx {C Function} scm_caar (pair)
+@deffnx {C Function} scm_cdddr (pair)
+@deffnx {C Function} scm_cddar (pair)
+@deffnx {C Function} scm_cdadr (pair)
+@deffnx {C Function} scm_cdaar (pair)
+@deffnx {C Function} scm_caddr (pair)
+@deffnx {C Function} scm_cadar (pair)
+@deffnx {C Function} scm_caadr (pair)
+@deffnx {C Function} scm_caaar (pair)
+@deffnx {C Function} scm_cddddr (pair)
+@deffnx {C Function} scm_cdddar (pair)
+@deffnx {C Function} scm_cddadr (pair)
+@deffnx {C Function} scm_cddaar (pair)
+@deffnx {C Function} scm_cdaddr (pair)
+@deffnx {C Function} scm_cdadar (pair)
+@deffnx {C Function} scm_cdaadr (pair)
+@deffnx {C Function} scm_cdaaar (pair)
+@deffnx {C Function} scm_cadddr (pair)
+@deffnx {C Function} scm_caddar (pair)
+@deffnx {C Function} scm_cadadr (pair)
+@deffnx {C Function} scm_cadaar (pair)
+@deffnx {C Function} scm_caaddr (pair)
+@deffnx {C Function} scm_caadar (pair)
+@deffnx {C Function} scm_caaadr (pair)
+@deffnx {C Function} scm_caaaar (pair)
 These procedures are compositions of @code{car} and @code{cdr}, where
 for example @code{caddr} could be defined by
 
@@ -202,9 +273,10 @@ up a list.  An example will clear that up:
 ()
 @end lisp
 
-This example also shows that lists have to be quoted (REFFIXME) when
-written, because they would otherwise be mistakingly taken as procedure
-applications (@pxref{Simple Invocation}).
+This example also shows that lists have to be quoted when written
+(@pxref{Expression Syntax}), because they would otherwise be
+mistakingly taken as procedure applications (@pxref{Simple
+Invocation}).
 
 
 @node List Predicates
@@ -232,6 +304,11 @@ somehow deals with the elements of a list until the list satisfies
 Return @code{#t} iff @var{x} is the empty list, else @code{#f}.
 @end deffn
 
+@deftypefn {C Function} int scm_is_null (SCM x)
+Return 1 when @var{x} is the empty list; otherwise return 0.
+@end deftypefn
+
+
 @node List Constructors
 @subsubsection List Constructors
 
@@ -308,7 +385,7 @@ Return the number of elements in list @var{lst}.
 
 @deffn {Scheme Procedure} last-pair lst
 @deffnx {C Function} scm_last_pair (lst)
-Return a pointer to the last pair in @var{lst}, signalling an error if
+Return the last pair in @var{lst}, signalling an error if
 @var{lst} is circular.
 @end deffn
 
@@ -476,7 +553,9 @@ predicate @var{pred}.  The elements in the result list have the same
 order as in @var{lst}.  The order in which @var{pred} is applied to
 the list elements is not specified.
 
-@code{filter!} is allowed, but not required to modify the structure of
+@code{filter} does not change @var{lst}, but the result may share a
+tail with it.  @code{filter!} may modify @var{lst} to construct its
+return.
 @end deffn
 
 @node List Searching
@@ -566,15 +645,18 @@ given its @dfn{position} (synonymous with @dfn{index}), a zero-origin number,
 is constant, whereas lists have an access time linear to the position of the
 accessed element in the list.
 
-Vectors can contain any kind of Scheme object; it is even possible to have
-different types of objects in the same vector.  For vectors containing
-vectors, you may wish to use arrays, instead.  Note, too, that some array
-procedures operate happily on vectors (@pxref{Arrays}).
+Vectors can contain any kind of Scheme object; it is even possible to
+have different types of objects in the same vector.  For vectors
+containing vectors, you may wish to use arrays, instead.  Note, too,
+that vectors are the special case of one dimensional non-uniform arrays
+and that most array procedures operate happily on vectors
+(@pxref{Arrays}).
 
 @menu
 * Vector Syntax::               Read syntax for vectors.
 * Vector Creation::             Dynamic vector creation and validation.
 * Vector Accessors::            Accessing and modifying vector contents.
+* Vector Accessing from C::     Ways to work with vectors from C.
 @end menu
 
 
@@ -595,7 +677,7 @@ number in hexadecimal notation.
 #("Hello" foo #xdeadbeef)
 @end lisp
 
-Like lists, vectors have to be quoted (REFFIXME):
+Like lists, vectors have to be quoted:
 
 @lisp
 '#(a b c) @result{} #(a b c)
@@ -623,12 +705,6 @@ given arguments.  Analogous to @code{list}.
 @end lisp
 @end deffn
 
-(As an aside, an interesting implementation detail is that the Guile
-reader reads the @code{#(@dots{})} syntax by reading everything but the
-initial @code{#} as a @emph{list}, and then passing the list that
-results to @code{list->vector}.  Notice how neatly this fits with the
-similarity between the read (and print) syntaxes for lists and vectors.)
-
 The inverse operation is @code{vector->list}:
 
 @rnindex vector->list
@@ -648,14 +724,18 @@ value for the vector elements (the same value for all elements, that
 is):
 
 @rnindex make-vector
-@deffn {Scheme Procedure} make-vector k [fill]
-@deffnx {C Function} scm_make_vector (k, fill)
-Return a newly allocated vector of @var{k} elements.  If a
+@deffn {Scheme Procedure} make-vector len [fill]
+@deffnx {C Function} scm_make_vector (len, fill)
+Return a newly allocated vector of @var{len} elements.  If a
 second argument is given, then each position is initialized to
 @var{fill}.  Otherwise the initial contents of each position is
 unspecified.
 @end deffn
 
+@deftypefn {C Function} SCM scm_c_make_vector (size_t k, SCM fill)
+Like @code{scm_make_vector}, but the length is given as a @code{size_t}.
+@end deftypefn
+
 To check whether an arbitrary Scheme value @emph{is} a vector, use the
 @code{vector?} primitive:
 
@@ -666,6 +746,10 @@ Return @code{#t} if @var{obj} is a vector, otherwise return
 @code{#f}.
 @end deffn
 
+@deftypefn {C Function} int scm_is_vector (SCM obj)
+Return non-zero when @var{obj} is a vector, otherwise return
+@code{zero}.
+@end deftypefn
 
 @node Vector Accessors
 @subsubsection Accessing and Modifying Vector Contents
@@ -680,6 +764,10 @@ in the vector.
 Return the number of elements in @var{vector} as an exact integer.
 @end deffn
 
+@deftypefn {C Function} size_t scm_c_vector_length (SCM v)
+Return the number of elements in @var{vector} as a @code{size_t}.
+@end deftypefn
+
 @rnindex vector-ref
 @deffn {Scheme Procedure} vector-ref vector k
 @deffnx {C Function} scm_vector_ref vector k
@@ -695,6 +783,11 @@ Return the contents of position @var{k} of @var{vector}.
 @end lisp
 @end deffn
 
+@deftypefn {C Function} SCM scm_c_vector_ref (SCM v, size_t k)
+Return the contents of position @var{k} (a @code{size_t}) of
+@var{vector}.
+@end deftypefn
+
 A vector created by one of the dynamic vector constructor procedures
 (@pxref{Vector Creation}) can be modified using the following
 procedures.
@@ -717,6 +810,10 @@ The value returned by @samp{vector-set!} is unspecified.
 @end lisp
 @end deffn
 
+@deftypefn {C Function} void scm_c_vector_set_x (SCM v, size_t k, SCM obj)
+Store @var{obj} in position @var{k} (a @code{size_t}) of @var{v}.
+@end deftypefn
+
 @rnindex vector-fill!
 @deffn {Scheme Procedure} vector-fill! v fill
 @deffnx {C Function} scm_vector_fill_x (v, fill)
@@ -724,6 +821,11 @@ Store @var{fill} in every position of @var{vector}.  The value
 returned by @code{vector-fill!} is unspecified.
 @end deffn
 
+@deffn {Scheme Procedure} vector-copy vec
+@deffnx {C Function} scm_vector_copy (vec)
+Return a copy of @var{vec}.
+@end deffn
+
 @deffn {Scheme Procedure} vector-move-left! vec1 start1 end1 vec2 start2
 @deffnx {C Function} scm_vector_move_left_x (vec1, start1, end1, vec2, start2)
 Copy elements from @var{vec1}, positions @var{start1} to @var{end1},
@@ -748,457 +850,972 @@ same vector, @code{vector-move-right!} is usually appropriate when
 @var{start1} is less than @var{start2}.
 @end deffn
 
+@node Vector Accessing from C
+@subsubsection Vector Accessing from C
+
+A vector can be read and modified from C with the functions
+@code{scm_c_vector_ref} and @code{scm_c_vector_set_x}, for example.  In
+addition to these functions, there are two more ways to access vectors
+from C that might be more efficient in certain situations: you can
+restrict yourself to @dfn{simple vectors} and then use the very fast
+@emph{simple vector macros}; or you can use the very general framework
+for accessing all kinds of arrays (@pxref{Accessing Arrays from C}),
+which is more verbose, but can deal efficiently with all kinds of
+vectors (and arrays).  For vectors, you can use the
+@code{scm_vector_elements} and @code{scm_vector_writable_elements}
+functions as shortcuts.
+
+@deftypefn {C Function} int scm_is_simple_vector (SCM obj)
+Return non-zero if @var{obj} is a simple vector, else return zero.  A
+simple vector is a vector that can be used with the @code{SCM_SIMPLE_*}
+macros below.
+
+The following functions are guaranteed to return simple vectors:
+@code{scm_make_vector}, @code{scm_c_make_vector}, @code{scm_vector},
+@code{scm_list_to_vector}.
+@end deftypefn
+
+@deftypefn {C Macro} size_t SCM_SIMPLE_VECTOR_LENGTH (SCM vec)
+Evaluates to the length of the simple vector @var{vec}.  No type
+checking is done.
+@end deftypefn
+
+@deftypefn {C Macro} SCM SCM_SIMPLE_VECTOR_REF (SCM vec, size_t idx)
+Evaluates to the element at position @var{idx} in the simple vector
+@var{vec}.  No type or range checking is done.
+@end deftypefn
+
+@deftypefn {C Macro} void SCM_SIMPLE_VECTOR_SET (SCM vec, size_t idx, SCM val)
+Sets the element at position @var{idx} in the simple vector
+@var{vec} to @var{val}.  No type or range checking is done.
+@end deftypefn
+
+@deftypefn {C Function} {const SCM *} scm_vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+Acquire a handle for the vector @var{vec} and return a pointer to the
+elements of it.  This pointer can only be used to read the elements of
+@var{vec}.  When @var{vec} is not a vector, an error is signaled.  The
+handle mustr eventually be released with
+@code{scm_array_handle_release}.
+
+The variables pointed to by @var{lenp} and @var{incp} are filled with
+the number of elements of the vector and the increment (number of
+elements) between successive elements, respectively.  Successive
+elements of @var{vec} need not be contiguous in their underlying
+``root vector'' returned here; hence the increment is not necessarily
+equal to 1 and may well be negative too (@pxref{Shared Arrays}).
+
+The following example shows the typical way to use this function.  It
+creates a list of all elements of @var{vec} (in reverse order).
 
-@node Records
-@subsection Records
-
-A @dfn{record type} is a first class object representing a user-defined
-data type.  A @dfn{record} is an instance of a record type.
-
-@deffn {Scheme Procedure} record? obj
-Return @code{#t} if @var{obj} is a record of any type and @code{#f}
-otherwise.
+@example
+scm_t_array_handle handle;
+size_t i, len;
+ssize_t inc;
+const SCM *elt;
+SCM list;
+
+elt = scm_vector_elements (vec, &handle, &len, &inc);
+list = SCM_EOL;
+for (i = 0; i < len; i++, elt += inc)
+  list = scm_cons (*elt, list);
+scm_array_handle_release (&handle);
+@end example
 
-Note that @code{record?} may be true of any Scheme value; there is no
-promise that records are disjoint with other Scheme types.
-@end deffn
+@end deftypefn
 
-@deffn {Scheme Procedure} make-record-type type-name field-names
-Return a @dfn{record-type descriptor}, a value representing a new data
-type disjoint from all others.  The @var{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 @var{field-names}
-argument is a list of symbols naming the @dfn{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.
-@end deffn
+@deftypefn {C Function} {SCM *} scm_vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+Like @code{scm_vector_elements} but the pointer can be used to modify
+the vector.
 
-@deffn {Scheme Procedure} record-constructor rtd [field-names]
-Return a procedure for constructing new members of the type represented
-by @var{rtd}.  The returned procedure accepts exactly as many arguments
-as there are symbols in the given list, @var{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 @var{field-names}
-argument defaults to the list of field names in the call to
-@code{make-record-type} that created the type represented by @var{rtd};
-if the @var{field-names} argument is provided, it is an error if it
-contains any duplicates or any symbols not in the default list.
-@end deffn
+The following example shows the typical way to use this function.  It
+fills a vector with @code{#t}.
 
-@deffn {Scheme Procedure} record-predicate rtd
-Return a procedure for testing membership in the type represented by
-@var{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.
-@end deffn
+@example
+scm_t_array_handle handle;
+size_t i, len;
+ssize_t inc;
+SCM *elt;
+
+elt = scm_vector_writable_elements (vec, &handle, &len, &inc);
+for (i = 0; i < len; i++, elt += inc)
+  *elt = SCM_BOOL_T;
+scm_array_handle_release (&handle);
+@end example
 
-@deffn {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 @var{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
-@var{field-name} in that record.  The symbol @var{field-name} must be a
-member of the list of field-names in the call to @code{make-record-type}
-that created the type represented by @var{rtd}.
-@end deffn
+@end deftypefn
+
+@node Uniform Numeric Vectors
+@subsection Uniform Numeric Vectors
+
+A uniform numeric vector is a vector whose elements are all of a single
+numeric type.  Guile offers uniform numeric vectors for signed and
+unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of
+floating point values, and complex floating-point numbers of these two
+sizes.
+
+Strings could be regarded as uniform vectors of characters,
+@xref{Strings}.  Likewise, bit vectors could be regarded as uniform
+vectors of bits, @xref{Bit Vectors}.  Both are sufficiently different
+from uniform numeric vectors that the procedures described here do not
+apply to these two data types.  However, both strings and bit vectors
+are generalized vectors, @xref{Generalized Vectors}, and arrays,
+@xref{Arrays}.
+
+Uniform numeric vectors are the special case of one dimensional uniform
+numeric arrays.
+
+Uniform numeric vectors can be useful since they consume less memory
+than the non-uniform, general vectors.  Also, since the types they can
+store correspond directly to C types, it is easier to work with them
+efficiently on a low level.  Consider image processing as an example,
+where you want to apply a filter to some image.  While you could store
+the pixels of an image in a general vector and write a general
+convolution function, things are much more efficient with uniform
+vectors: the convolution function knows that all pixels are unsigned
+8-bit values (say), and can use a very tight inner loop.
+
+That is, when it is written in C.  Functions for efficiently working
+with uniform numeric vectors from C are listed at the end of this
+section.
+
+Procedures similar to the vector procedures (@pxref{Vectors}) are
+provided for handling these uniform vectors, but they are distinct
+datatypes and the two cannot be inter-mixed.  If you want to work
+primarily with uniform numeric vectors, but want to offer support for
+general vectors as a convenience, you can use one of the
+@code{scm_any_to_*} functions.  They will coerce lists and vectors to
+the given type of uniform vector.  Alternatively, you can write two
+versions of your code: one that is fast and works only with uniform
+numeric vectors, and one that works with any kind of vector but is
+slower.
+
+One set of the procedures listed below is a generic one: it works with
+all types of uniform numeric vectors.  In addition to that, there is a
+set of procedures for each type that only works with that type.  Unless
+you really need to the generality of the first set, it is best to use
+the more specific functions.  They might not be that much faster, but
+their use can serve as a kind of declaration and makes it easier to
+optimize later on.
+
+The generic set of procedures uses @code{uniform} in its names, the
+specific ones use the tag from the following table.
+
+@table @nicode
+@item u8
+unsigned 8-bit integers
+
+@item s8
+signed 8-bit integers
+
+@item u16
+unsigned 16-bit integers
+
+@item s16
+signed 16-bit integers
+
+@item u32
+unsigned 32-bit integers
+
+@item s32
+signed 32-bit integers
+
+@item u64
+unsigned 64-bit integers
+
+@item s64
+signed 64-bit integers
+
+@item f32
+the C type @code{float}
+
+@item f64
+the C type @code{double}
+
+@item c32
+complex numbers in rectangular form with the real and imaginary part
+being a @code{float}
+
+@item c64
+complex numbers in rectangular form with the real and imaginary part
+being a @code{double}
+
+@end table
+
+The external representation (ie.@: read syntax) for these vectors is
+similar to normal Scheme vectors, but with an additional tag from the
+tabel above indiciating the vector's type.  For example,
 
-@deffn {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 @var{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 @var{field-name} in that record to contain the given value.
-The returned value of the modifier procedure is unspecified.  The symbol
-@var{field-name} must be a member of the list of field-names in the call
-to @code{make-record-type} that created the type represented by
-@var{rtd}.
-@end deffn
+@lisp
+#u16(1 2 3)
+#f64(3.1415 2.71)
+@end lisp
 
-@deffn {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
-@code{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
-@code{record-constructor} in the call that created the constructor
-procedure that created the given record.
+Note that the read syntax for floating-point here conflicts with
+@code{#f} for false.  In Standard Scheme one can write @code{(1 #f3)}
+for a three element list @code{(1 #f 3)}, but for Guile @code{(1 #f3)}
+is invalid.  @code{(1 #f 3)} is almost certainly what one should write
+anyway to make the intention clear, so this is rarely a problem.
+
+@deffn  {Scheme Procedure} uniform-vector? obj
+@deffnx {Scheme Procedure} u8vector? obj
+@deffnx {Scheme Procedure} s8vector? obj
+@deffnx {Scheme Procedure} u16vector? obj
+@deffnx {Scheme Procedure} s16vector? obj
+@deffnx {Scheme Procedure} u32vector? obj
+@deffnx {Scheme Procedure} s32vector? obj
+@deffnx {Scheme Procedure} u64vector? obj
+@deffnx {Scheme Procedure} s64vector? obj
+@deffnx {Scheme Procedure} f32vector? obj
+@deffnx {Scheme Procedure} f64vector? obj
+@deffnx {Scheme Procedure} c32vector? obj
+@deffnx {Scheme Procedure} c64vector? obj
+@deffnx {C Function} scm_uniform_vector_p (obj)
+@deffnx {C Function} scm_u8vector_p (obj)
+@deffnx {C Function} scm_s8vector_p (obj)
+@deffnx {C Function} scm_u16vector_p (obj)
+@deffnx {C Function} scm_s16vector_p (obj)
+@deffnx {C Function} scm_u32vector_p (obj)
+@deffnx {C Function} scm_s32vector_p (obj)
+@deffnx {C Function} scm_u64vector_p (obj)
+@deffnx {C Function} scm_s64vector_p (obj)
+@deffnx {C Function} scm_f32vector_p (obj)
+@deffnx {C Function} scm_f64vector_p (obj)
+@deffnx {C Function} scm_c32vector_p (obj)
+@deffnx {C Function} scm_c64vector_p (obj)
+Return @code{#t} if @var{obj} is a homogeneous numeric vector of the
+indicated type.
+@end deffn
+
+@deffn  {Scheme Procedure} make-u8vector n [value]
+@deffnx {Scheme Procedure} make-s8vector n [value]
+@deffnx {Scheme Procedure} make-u16vector n [value]
+@deffnx {Scheme Procedure} make-s16vector n [value]
+@deffnx {Scheme Procedure} make-u32vector n [value]
+@deffnx {Scheme Procedure} make-s32vector n [value]
+@deffnx {Scheme Procedure} make-u64vector n [value]
+@deffnx {Scheme Procedure} make-s64vector n [value]
+@deffnx {Scheme Procedure} make-f32vector n [value]
+@deffnx {Scheme Procedure} make-f64vector n [value]
+@deffnx {Scheme Procedure} make-c32vector n [value]
+@deffnx {Scheme Procedure} make-c64vector n [value]
+@deffnx {C Function} scm_make_u8vector n [value]
+@deffnx {C Function} scm_make_s8vector n [value]
+@deffnx {C Function} scm_make_u16vector n [value]
+@deffnx {C Function} scm_make_s16vector n [value]
+@deffnx {C Function} scm_make_u32vector n [value]
+@deffnx {C Function} scm_make_s32vector n [value]
+@deffnx {C Function} scm_make_u64vector n [value]
+@deffnx {C Function} scm_make_s64vector n [value]
+@deffnx {C Function} scm_make_f32vector n [value]
+@deffnx {C Function} scm_make_f64vector n [value]
+@deffnx {C Function} scm_make_c32vector n [value]
+@deffnx {C Function} scm_make_c64vector n [value]
+Return a newly allocated homogeneous numeric vector holding @var{n}
+elements of the indicated type.  If @var{value} is given, the vector
+is initialized with that value, otherwise the contents are
+unspecified.
 @end deffn
 
-@deffn {Scheme Procedure} record-type-name rtd
-Return the type-name associated with the type represented by rtd.  The
-returned value is @code{eqv?} to the @var{type-name} argument given in
-the call to @code{make-record-type} that created the type represented by
-@var{rtd}.
+@deffn  {Scheme Procedure} u8vector value @dots{}
+@deffnx {Scheme Procedure} s8vector value @dots{}
+@deffnx {Scheme Procedure} u16vector value @dots{}
+@deffnx {Scheme Procedure} s16vector value @dots{}
+@deffnx {Scheme Procedure} u32vector value @dots{}
+@deffnx {Scheme Procedure} s32vector value @dots{}
+@deffnx {Scheme Procedure} u64vector value @dots{}
+@deffnx {Scheme Procedure} s64vector value @dots{}
+@deffnx {Scheme Procedure} f32vector value @dots{}
+@deffnx {Scheme Procedure} f64vector value @dots{}
+@deffnx {Scheme Procedure} c32vector value @dots{}
+@deffnx {Scheme Procedure} c64vector value @dots{}
+@deffnx {C Function} scm_u8vector (values)
+@deffnx {C Function} scm_s8vector (values)
+@deffnx {C Function} scm_u16vector (values)
+@deffnx {C Function} scm_s16vector (values)
+@deffnx {C Function} scm_u32vector (values)
+@deffnx {C Function} scm_s32vector (values)
+@deffnx {C Function} scm_u64vector (values)
+@deffnx {C Function} scm_s64vector (values)
+@deffnx {C Function} scm_f32vector (values)
+@deffnx {C Function} scm_f64vector (values)
+@deffnx {C Function} scm_c32vector (values)
+@deffnx {C Function} scm_c64vector (values)
+Return a newly allocated homogeneous numeric vector of the indicated
+type, holding the given parameter @var{value}s.  The vector length is
+the number of parameters given.
+@end deffn
+
+@deffn  {Scheme Procedure} uniform-vector-length vec
+@deffnx {Scheme Procedure} u8vector-length vec
+@deffnx {Scheme Procedure} s8vector-length vec
+@deffnx {Scheme Procedure} u16vector-length vec
+@deffnx {Scheme Procedure} s16vector-length vec
+@deffnx {Scheme Procedure} u32vector-length vec
+@deffnx {Scheme Procedure} s32vector-length vec
+@deffnx {Scheme Procedure} u64vector-length vec
+@deffnx {Scheme Procedure} s64vector-length vec
+@deffnx {Scheme Procedure} f32vector-length vec
+@deffnx {Scheme Procedure} f64vector-length vec
+@deffnx {Scheme Procedure} c32vector-length vec
+@deffnx {Scheme Procedure} c64vector-length vec
+@deffnx {C Function} scm_uniform_vector_length (vec)
+@deffnx {C Function} scm_u8vector_length (vec)
+@deffnx {C Function} scm_s8vector_length (vec)
+@deffnx {C Function} scm_u16vector_length (vec)
+@deffnx {C Function} scm_s16vector_length (vec)
+@deffnx {C Function} scm_u32vector_length (vec)
+@deffnx {C Function} scm_s32vector_length (vec)
+@deffnx {C Function} scm_u64vector_length (vec)
+@deffnx {C Function} scm_s64vector_length (vec)
+@deffnx {C Function} scm_f32vector_length (vec)
+@deffnx {C Function} scm_f64vector_length (vec)
+@deffnx {C Function} scm_c32vector_length (vec)
+@deffnx {C Function} scm_c64vector_length (vec)
+Return the number of elements in @var{vec}.
+@end deffn
+
+@deffn  {Scheme Procedure} uniform-vector-ref vec i
+@deffnx {Scheme Procedure} u8vector-ref vec i
+@deffnx {Scheme Procedure} s8vector-ref vec i
+@deffnx {Scheme Procedure} u16vector-ref vec i
+@deffnx {Scheme Procedure} s16vector-ref vec i
+@deffnx {Scheme Procedure} u32vector-ref vec i
+@deffnx {Scheme Procedure} s32vector-ref vec i
+@deffnx {Scheme Procedure} u64vector-ref vec i
+@deffnx {Scheme Procedure} s64vector-ref vec i
+@deffnx {Scheme Procedure} f32vector-ref vec i
+@deffnx {Scheme Procedure} f64vector-ref vec i
+@deffnx {Scheme Procedure} c32vector-ref vec i
+@deffnx {Scheme Procedure} c64vector-ref vec i
+@deffnx {C Function} scm_uniform_vector_ref (vec i)
+@deffnx {C Function} scm_u8vector_ref (vec i)
+@deffnx {C Function} scm_s8vector_ref (vec i)
+@deffnx {C Function} scm_u16vector_ref (vec i)
+@deffnx {C Function} scm_s16vector_ref (vec i)
+@deffnx {C Function} scm_u32vector_ref (vec i)
+@deffnx {C Function} scm_s32vector_ref (vec i)
+@deffnx {C Function} scm_u64vector_ref (vec i)
+@deffnx {C Function} scm_s64vector_ref (vec i)
+@deffnx {C Function} scm_f32vector_ref (vec i)
+@deffnx {C Function} scm_f64vector_ref (vec i)
+@deffnx {C Function} scm_c32vector_ref (vec i)
+@deffnx {C Function} scm_c64vector_ref (vec i)
+Return the element at index @var{i} in @var{vec}.  The first element
+in @var{vec} is index 0.
+@end deffn
+
+@deffn  {Scheme Procedure} uniform-vector-set! vec i value
+@deffnx {Scheme Procedure} u8vector-set! vec i value
+@deffnx {Scheme Procedure} s8vector-set! vec i value
+@deffnx {Scheme Procedure} u16vector-set! vec i value
+@deffnx {Scheme Procedure} s16vector-set! vec i value
+@deffnx {Scheme Procedure} u32vector-set! vec i value
+@deffnx {Scheme Procedure} s32vector-set! vec i value
+@deffnx {Scheme Procedure} u64vector-set! vec i value
+@deffnx {Scheme Procedure} s64vector-set! vec i value
+@deffnx {Scheme Procedure} f32vector-set! vec i value
+@deffnx {Scheme Procedure} f64vector-set! vec i value
+@deffnx {Scheme Procedure} c32vector-set! vec i value
+@deffnx {Scheme Procedure} c64vector-set! vec i value
+@deffnx {C Function} scm_uniform_vector_set_x (vec i value)
+@deffnx {C Function} scm_u8vector_set_x (vec i value)
+@deffnx {C Function} scm_s8vector_set_x (vec i value)
+@deffnx {C Function} scm_u16vector_set_x (vec i value)
+@deffnx {C Function} scm_s16vector_set_x (vec i value)
+@deffnx {C Function} scm_u32vector_set_x (vec i value)
+@deffnx {C Function} scm_s32vector_set_x (vec i value)
+@deffnx {C Function} scm_u64vector_set_x (vec i value)
+@deffnx {C Function} scm_s64vector_set_x (vec i value)
+@deffnx {C Function} scm_f32vector_set_x (vec i value)
+@deffnx {C Function} scm_f64vector_set_x (vec i value)
+@deffnx {C Function} scm_c32vector_set_x (vec i value)
+@deffnx {C Function} scm_c64vector_set_x (vec i value)
+Set the element at index @var{i} in @var{vec} to @var{value}.  The
+first element in @var{vec} is index 0.  The return value is
+unspecified.
 @end deffn
 
-@deffn {Scheme Procedure} record-type-fields rtd
-Return a list of the symbols naming the fields in members of the type
-represented by @var{rtd}.  The returned value is @code{equal?} to the
-field-names argument given in the call to @code{make-record-type} that
-created the type represented by @var{rtd}.
-@end deffn
+@deffn  {Scheme Procedure} uniform-vector->list vec
+@deffnx {Scheme Procedure} u8vector->list vec
+@deffnx {Scheme Procedure} s8vector->list vec
+@deffnx {Scheme Procedure} u16vector->list vec
+@deffnx {Scheme Procedure} s16vector->list vec
+@deffnx {Scheme Procedure} u32vector->list vec
+@deffnx {Scheme Procedure} s32vector->list vec
+@deffnx {Scheme Procedure} u64vector->list vec
+@deffnx {Scheme Procedure} s64vector->list vec
+@deffnx {Scheme Procedure} f32vector->list vec
+@deffnx {Scheme Procedure} f64vector->list vec
+@deffnx {Scheme Procedure} c32vector->list vec
+@deffnx {Scheme Procedure} c64vector->list vec
+@deffnx {C Function} scm_uniform_vector_to_list (vec)
+@deffnx {C Function} scm_u8vector_to_list (vec)
+@deffnx {C Function} scm_s8vector_to_list (vec)
+@deffnx {C Function} scm_u16vector_to_list (vec)
+@deffnx {C Function} scm_s16vector_to_list (vec)
+@deffnx {C Function} scm_u32vector_to_list (vec)
+@deffnx {C Function} scm_s32vector_to_list (vec)
+@deffnx {C Function} scm_u64vector_to_list (vec)
+@deffnx {C Function} scm_s64vector_to_list (vec)
+@deffnx {C Function} scm_f32vector_to_list (vec)
+@deffnx {C Function} scm_f64vector_to_list (vec)
+@deffnx {C Function} scm_c32vector_to_list (vec)
+@deffnx {C Function} scm_c64vector_to_list (vec)
+Return a newly allocated list holding all elements of @var{vec}.
+@end deffn
+
+@deffn  {Scheme Procedure} list->u8vector lst
+@deffnx {Scheme Procedure} list->s8vector lst
+@deffnx {Scheme Procedure} list->u16vector lst
+@deffnx {Scheme Procedure} list->s16vector lst
+@deffnx {Scheme Procedure} list->u32vector lst
+@deffnx {Scheme Procedure} list->s32vector lst
+@deffnx {Scheme Procedure} list->u64vector lst
+@deffnx {Scheme Procedure} list->s64vector lst
+@deffnx {Scheme Procedure} list->f32vector lst
+@deffnx {Scheme Procedure} list->f64vector lst
+@deffnx {Scheme Procedure} list->c32vector lst
+@deffnx {Scheme Procedure} list->c64vector lst
+@deffnx {C Function} scm_list_to_u8vector (lst)
+@deffnx {C Function} scm_list_to_s8vector (lst)
+@deffnx {C Function} scm_list_to_u16vector (lst)
+@deffnx {C Function} scm_list_to_s16vector (lst)
+@deffnx {C Function} scm_list_to_u32vector (lst)
+@deffnx {C Function} scm_list_to_s32vector (lst)
+@deffnx {C Function} scm_list_to_u64vector (lst)
+@deffnx {C Function} scm_list_to_s64vector (lst)
+@deffnx {C Function} scm_list_to_f32vector (lst)
+@deffnx {C Function} scm_list_to_f64vector (lst)
+@deffnx {C Function} scm_list_to_c32vector (lst)
+@deffnx {C Function} scm_list_to_c64vector (lst)
+Return a newly allocated homogeneous numeric vector of the indicated type,
+initialized with the elements of the list @var{lst}.
+@end deffn
+
+@deffn  {Scheme Procedure} any->u8vector obj
+@deffnx {Scheme Procedure} any->s8vector obj
+@deffnx {Scheme Procedure} any->u16vector obj
+@deffnx {Scheme Procedure} any->s16vector obj
+@deffnx {Scheme Procedure} any->u32vector obj
+@deffnx {Scheme Procedure} any->s32vector obj
+@deffnx {Scheme Procedure} any->u64vector obj
+@deffnx {Scheme Procedure} any->s64vector obj
+@deffnx {Scheme Procedure} any->f32vector obj
+@deffnx {Scheme Procedure} any->f64vector obj
+@deffnx {Scheme Procedure} any->c32vector obj
+@deffnx {Scheme Procedure} any->c64vector obj
+@deffnx {C Function} scm_any_to_u8vector (obj)
+@deffnx {C Function} scm_any_to_s8vector (obj)
+@deffnx {C Function} scm_any_to_u16vector (obj)
+@deffnx {C Function} scm_any_to_s16vector (obj)
+@deffnx {C Function} scm_any_to_u32vector (obj)
+@deffnx {C Function} scm_any_to_s32vector (obj)
+@deffnx {C Function} scm_any_to_u64vector (obj)
+@deffnx {C Function} scm_any_to_s64vector (obj)
+@deffnx {C Function} scm_any_to_f32vector (obj)
+@deffnx {C Function} scm_any_to_f64vector (obj)
+@deffnx {C Function} scm_any_to_c32vector (obj)
+@deffnx {C Function} scm_any_to_c64vector (obj)
+Return a (maybe newly allocated) uniform numeric vector of the indicated
+type, initialized with the elements of @var{obj}, which must be a list,
+a vector, or a uniform vector.  When @var{obj} is already a suitable
+uniform numeric vector, it is returned unchanged.
+@end deffn
+
+@deftypefn {C Function} int scm_is_uniform_vector (SCM uvec)
+Return non-zero when @var{uvec} is a uniform numeric vector, zero
+otherwise.
+@end deftypefn
+
+@deftypefn  {C Function} SCM scm_take_u8vector (const scm_t_uint8 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_s8vector (const scm_t_int8 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_u16vector (const scm_t_uint16 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_s168vector (const scm_t_int16 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_u32vector (const scm_t_uint32 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_s328vector (const scm_t_int32 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_u64vector (const scm_t_uint64 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_s64vector (const scm_t_int64 *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_f32vector (const float *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_f64vector (const double *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_c32vector (const float *data, size_t len)
+@deftypefnx {C Function} SCM scm_take_c64vector (const double *data, size_t len)
+Return a new uniform numeric vector of the indicated type and length
+that uses the memory pointed to by @var{data} to store its elements.
+This memory will eventually be freed with @code{free}.  The argument
+@var{len} specifies the number of elements in @var{data}, not its size
+in bytes.
+
+The @code{c32} and @code{c64} variants take a pointer to a C array of
+@code{float}s or @code{double}s.  The real parts of the complex numbers
+are at even indices in that array, the corresponding imaginary parts are
+at the following odd index.
+@end deftypefn
+
+@deftypefn {C Function} size_t scm_c_uniform_vector_length (SCM uvec)
+Return the number of elements of @var{uvec} as a @code{size_t}.
+@end deftypefn
+
+@deftypefn  {C Function} {const void *} scm_uniform_vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_uint8 *} scm_u8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_int8 *} scm_s8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_uint16 *} scm_u16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_int16 *} scm_s16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_uint32 *} scm_u32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_int32 *} scm_s32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_uint64 *} scm_u64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const scm_t_int64 *} scm_s64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const float *} scm_f23vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const double *} scm_f64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const float *} scm_c32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {const double *} scm_c64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+Like @code{scm_vector_elements} (@pxref{Vector Accessing from C}), but
+returns a pointer to the elements of a uniform numeric vector of the
+indicated kind.
+@end deftypefn
+
+@deftypefn  {C Function} {void *} scm_uniform_vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_uint8 *} scm_u8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_int8 *} scm_s8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_uint16 *} scm_u16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_int16 *} scm_s16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_uint32 *} scm_u32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_int32 *} scm_s32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_uint64 *} scm_u64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {scm_t_int64 *} scm_s64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {float *} scm_f23vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {double *} scm_f64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {float *} scm_c32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@deftypefnx {C Function} {double *} scm_c64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+Like @code{scm_vector_writable_elements} (@pxref{Vector Accessing from
+C}), but returns a pointer to the elements of a uniform numeric vector
+of the indicated kind.
+@end deftypefn
+
+@deffn {Scheme Procedure} uniform-vector-read! uvec [port_or_fd [start [end]]]
+@deffnx {C Function} scm_uniform_vector_read_x (uvec, port_or_fd, start, end)
+Fill the elements of @var{uvec} by reading
+raw bytes from @var{port-or-fdes}, using host byte order.
+
+The optional arguments @var{start} (inclusive) and @var{end}
+(exclusive) allow a specified region to be read,
+leaving the remainder of the vector unchanged.
 
+When @var{port-or-fdes} is a port, all specified elements
+of @var{uvec} are attempted to be read, potentially blocking
+while waiting formore input or end-of-file.
+When @var{port-or-fd} is an integer, a single call to
+read(2) is made.
 
-@node Structures
-@subsection Structures
-@tpindex Structures
+An error is signalled when the last element has only
+been partially filled before reaching end-of-file or in
+the single call to read(2).
 
-[FIXME: this is pasted in from Tom Lord's original guile.texi and should
-be reviewed]
+@code{uniform-vector-read!} returns the number of elements
+read.
 
-A @dfn{structure type} is a first class user-defined data type.  A
-@dfn{structure} is an instance of a structure type.  A structure type is
-itself a structure.
+@var{port-or-fdes} may be omitted, in which case it defaults
+to the value returned by @code{(current-input-port)}.
+@end deffn
 
-Structures are less abstract and more general than traditional records.
-In fact, in Guile Scheme, records are implemented using structures.
+@deffn {Scheme Procedure} uniform-vector-write uvec [port_or_fd [start [end]]]
+@deffnx {C Function} scm_uniform_vector_write (uvec, port_or_fd, start, end)
+Write the elements of @var{uvec} as raw bytes to
+@var{port-or-fdes}, in the host byte order.
 
-@menu
-* Structure Concepts::          The structure of Structures
-* Structure Layout::            Defining the layout of structure types
-* Structure Basics::            make-, -ref and -set! procedures for structs
-* Vtables::                     Accessing type-specific data
-@end menu
+The optional arguments @var{start} (inclusive)
+and @var{end} (exclusive) allow
+a specified region to be written.
 
-@node  Structure Concepts
-@subsubsection Structure Concepts
+When @var{port-or-fdes} is a port, all specified elements
+of @var{uvec} are attempted to be written, potentially blocking
+while waiting for more room.
+When @var{port-or-fd} is an integer, a single call to
+write(2) is made.
 
-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.
+An error is signalled when the last element has only
+been partially written in the single call to write(2).
 
-Three concepts are key to understanding structures.
+The number of objects actually written is returned.
+@var{port-or-fdes} may be
+omitted, in which case it defaults to the value returned by
+@code{(current-output-port)}.
+@end deffn
 
-@itemize @bullet{}
-@item @dfn{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.
+@node Bit Vectors
+@subsection Bit Vectors
 
-@item @dfn{structural accessors}
+@noindent
+Bit vectors are zero-origin, one-dimensional arrays of booleans.  They
+are displayed as a sequence of @code{0}s and @code{1}s prefixed by
+@code{#*}, e.g.,
 
-Structure access is by field number.   There is only one set of
-accessors common to all structure objects.
+@example
+(make-bitvector 8 #f) @result{}
+#*00000000
+@end example
 
-@item @dfn{vtables}
+Bit vectors are are also generalized vectors, @xref{Generalized
+Vectors}, and can thus be used with the array procedures, @xref{Arrays}.
+Bit vectors are the special case of one dimensional bit arrays.
 
-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.
-@end itemize
+@deffn {Scheme Procedure} bitvector? obj
+@deffnx {C Function} scm_bitvector_p (obj)
+Return @code{#t} when @var{obj} is a bitvector, else
+return @code{#f}.
+@end deffn
 
+@deftypefn {C Function} int scm_is_bitvector (SCM obj)
+Return @code{1} when @var{obj} is a bitvector, else return @code{0}.
+@end deftypefn
 
+@deffn {Scheme Procedure} make-bitvector len [fill]
+@deffnx {C Function} scm_make_bitvector (len, fill)
+Create a new bitvector of length @var{len} and
+optionally initialize all elements to @var{fill}.
+@end deffn
 
-@node  Structure Layout
-@subsubsection Structure Layout
+@deftypefn {C Function} SCM scm_c_make_bitvector (size_t len, SCM fill)
+Like @code{scm_make_bitvector}, but the length is given as a
+@code{size_t}.
+@end deftypefn
 
-When a structure is created, a region of memory is allocated to hold its
-state.  The @dfn{layout} of the structure's type determines how that
-memory is divided into fields.
+@deffn {Scheme Procedure} bitvector . bits
+@deffnx {C Function} scm_bitvector (bits)
+Create a new bitvector with the arguments as elements.
+@end deffn
 
-Each field has a specified type.  There are only three types allowed, each
-corresponding to a one letter code.  The allowed types are:
+@deffn {Scheme Procedure} bitvector-length vec
+@deffnx {C Function} scm_bitvector_length (vec)
+Return the length of the bitvector @var{vec}.
+@end deffn
 
-@itemize @bullet{}
-@item 'u' -- unprotected
+@deftypefn {C Function} size_t scm_c_bitvector_length (SCM vec)
+Like @code{scm_bitvector_length}, but the length is returned as a
+@code{size_t}.
+@end deftypefn
 
-The field holds binary data that is not GC protected.
+@deffn {Scheme Procedure} bitvector-ref vec idx
+@deffnx {C Function} scm_bitvector_ref (vec, idx)
+Return the element at index @var{idx} of the bitvector
+@var{vec}.
+@end deffn
 
-@item 'p' -- protected
+@deftypefn {C Function} SCM scm_c_bitvector_ref (SCM obj, size_t idx)
+Return the element at index @var{idx} of the bitvector
+@var{vec}.
+@end deftypefn
 
-The field holds a Scheme value and is GC protected.
+@deffn {Scheme Procedure} bitvector-set! vec idx val
+@deffnx {C Function} scm_bitvector_set_x (vec, idx, val)
+Set the element at index @var{idx} of the bitvector
+@var{vec} when @var{val} is true, else clear it.
+@end deffn
 
-@item 's' -- self
+@deftypefn {C Function} SCM scm_c_bitvector_set_x (SCM obj, size_t idx, SCM val)
+Set the element at index @var{idx} of the bitvector
+@var{vec} when @var{val} is true, else clear it.
+@end deftypefn
 
-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.
-@end itemize
+@deffn {Scheme Procedure} bitvector-fill! vec val
+@deffnx {C Function} scm_bitvector_fill_x (vec, val)
+Set all elements of the bitvector
+@var{vec} when @var{val} is true, else clear them.
+@end deffn
 
+@deffn {Scheme Procedure} list->bitvector list
+@deffnx {C Function} scm_list_to_bitvector (list)
+Return a new bitvector initialized with the elements
+of @var{list}.
+@end deffn
 
-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:
+@deffn {Scheme Procedure} bitvector->list vec
+@deffnx {C Function} scm_bitvector_to_list (vec)
+Return a new list initialized with the elements
+of the bitvector @var{vec}.
+@end deffn
 
-@itemize @bullet{}
-@item 'w' -- writable
+@deffn {Scheme Procedure} bit-count bool bitvector
+@deffnx {C Function} scm_bit_count (bool, bitvector)
+Return a count of how many entries in @var{bitvector} are equal to
+@var{bool}.  For example,
 
-The field can be read and written.
+@example
+(bit-count #f #*000111000)  @result{} 6
+@end example
+@end deffn
 
-@item 'r' -- readable
+@deffn {Scheme Procedure} bit-position bool bitvector start
+@deffnx {C Function} scm_bit_position (bool, bitvector, start)
+Return the index of the first occurrance of @var{bool} in
+@var{bitvector}, starting from @var{start}.  If there is no @var{bool}
+entry between @var{start} and the end of @var{bitvector}, then return
+@code{#f}.  For example,
 
-The field can be read, but not written.
+@example
+(bit-position #t #*000101 0)  @result{} 3
+(bit-position #f #*0001111 3) @result{} #f
+@end example
+@end deffn
 
-@item 'o' -- opaque
+@deffn {Scheme Procedure} bit-invert! bitvector
+@deffnx {C Function} scm_bit_invert_x (bitvector)
+Modify @var{bitvector} by replacing each element with its negation.
+@end deffn
 
-The field can be neither read nor written.   This kind
-of protection is for fields useful only to built-in routines.
-@end itemize
+@deffn {Scheme Procedure} bit-set*! bitvector uvec bool
+@deffnx {C Function} scm_bit_set_star_x (bitvector, uvec, bool)
+Set entries of @var{bitvector} to @var{bool}, with @var{uvec}
+selecting the entries to change.  The return value is unspecified.
 
-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:
+If @var{uvec} is a bit vector, then those entries where it has
+@code{#t} are the ones in @var{bitvector} which are set to @var{bool}.
+@var{uvec} and @var{bitvector} must be the same length.  When
+@var{bool} is @code{#t} it's like @var{uvec} is OR'ed into
+@var{bitvector}.  Or when @var{bool} is @code{#f} it can be seen as an
+ANDNOT.
 
 @example
-; cons pairs have two writable fields of Scheme data
-"pwpw"
+(define bv #*01000010)
+(bit-set*! bv #*10010001 #t)
+bv
+@result{} #*11010011
 @end example
 
-A pair object in which the first field is held constant could be:
+If @var{uvec} is a uniform vector of unsigned long integers, then
+they're indexes into @var{bitvector} which are set to @var{bool}.  
 
 @example
-"prpw"
+(define bv #*01000010)
+(bit-set*! bv #u(5 2 7) #t)
+bv
+@result{} #*01100111
 @end example
+@end deffn
 
-Binary fields, (fields of type "u"), hold one @dfn{word} each.  The
-size of a word is a machine dependent value defined to be equal to the
-value of the C expression: @code{sizeof (long)}.
+@deffn {Scheme Procedure} bit-count* bitvector uvec bool
+@deffnx {C Function} scm_bit_count_star (bitvector, uvec, bool)
+Return a count of how many entries in @var{bitvector} are equal to
+@var{bool}, with @var{uvec} selecting the entries to consider.
 
-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:
-
-@example
-; A vector is an arbitrary number of writable fields holding Scheme
-; values:
-"pW"
-@end example
-
-In the above example, field 0 contains the size of the vector and
-fields beginning at 1 contain the vector elements.
+@var{uvec} is interpreted in the same way as for @code{bit-set*!}
+above.  Namely, if @var{uvec} is a bit vector then entries which have
+@code{#t} there are considered in @var{bitvector}.  Or if @var{uvec}
+is a uniform vector of unsigned long integers then it's the indexes in
+@var{bitvector} to consider.
 
-A kind of tagged vector (a constant tag followed by conventional
-vector elements) might be:
+For example,
 
 @example
-"prpW"
+(bit-count* #*01110111 #*11001101 #t) @result{} 3
+(bit-count* #*01110111 #u(7 0 4) #f)  @result{} 2
 @end example
-
-
-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:
-
-@deffn {Scheme Procedure} make-struct-layout fields
-@deffnx {C Function} scm_make_struct_layout (fields)
-Return a new structure layout object.
-
-@var{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.
 @end deffn
 
+@deftypefn {C Function} {const scm_t_uint32 *} scm_bitvector_elements (SCM vec, scm_t_array_handle *handle, size_t *offp, size_t *lenp, ssize_t *incp)
+Like @code{scm_vector_elements} (@pxref{Vector Accessing from C}), but
+for bitvectors.  The variable pointed to by @var{offp} is set to the
+value returned by @code{scm_array_handle_bit_elements_offset}.  See
+@code{scm_array_handle_bit_elements} for how to use the returned
+pointer and the offset.
+@end deftypefn
 
+@deftypefn {C Function} {scm_t_uint32 *} scm_bitvector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *offp, size_t *lenp, ssize_t *incp)
+Like @code{scm_bitvector_elements}, but the pointer is good for reading
+and writing.
+@end deftypefn
 
-@node Structure Basics
-@subsubsection Structure Basics
-
-This section describes the basic procedures for creating and accessing
-structures.
-
-@deffn {Scheme Procedure} make-struct vtable tail_array_size . init
-@deffnx {C Function} scm_make_struct (vtable, tail_array_size, init)
-Create a new structure.
-
-@var{type} must be a vtable structure (@pxref{Vtables}).
-
-@var{tail-elts} must be a non-negative integer.  If the layout
-specification indicated by @var{type} includes a tail-array,
-this is the number of elements allocated to that array.
-
-The @var{init1}, @dots{} 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.
+@node Generalized Vectors
+@subsection Generalized Vectors
 
-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.
+Guile has a number of data types that are generally vector-like:
+strings, uniform numeric vectors, bitvectors, and of course ordinary
+vectors of arbitrary Scheme values.  These types are disjoint: a
+Scheme value belongs to at most one of the four types listed above.
 
-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.
+If you want to gloss over this distinction and want to treat all four
+types with common code, you can use the procedures in this section.
+They work with the @emph{generalized vector} type, which is the union
+of the four vector-like types.
 
-For more information, see the documentation for @code{make-vtable-vtable}.
+@deffn {Scheme Procedure} generalized-vector? obj
+@deffnx {C Function} scm_generalized_vector_p (obj)
+Return @code{#t} if @var{obj} is a vector, string,
+bitvector, or uniform numeric vector.
 @end deffn
 
-@deffn {Scheme Procedure} struct? x
-@deffnx {C Function} scm_struct_p (x)
-Return @code{#t} iff @var{x} is a structure object, else
-@code{#f}.
+@deffn {Scheme Procedure} generalized-vector-length v
+@deffnx {C Function} scm_generalized_vector_length (v)
+Return the length of the generalized vector @var{v}.
 @end deffn
 
-
-@deffn {Scheme Procedure} struct-ref handle pos
-@deffnx {Scheme Procedure} struct-set! struct n value
-@deffnx {C Function} scm_struct_ref (handle, pos)
-@deffnx {C Function} scm_struct_set_x (struct, n, value)
-Access (or modify) the @var{n}th field of @var{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.
+@deffn {Scheme Procedure} generalized-vector-ref v idx
+@deffnx {C Function} scm_generalized_vector_ref (v, idx)
+Return the element at index @var{idx} of the
+generalized vector @var{v}.
 @end deffn
 
+@deffn {Scheme Procedure} generalized-vector-set! v idx val
+@deffnx {C Function} scm_generalized_vector_set_x (v, idx, val)
+Set the element at index @var{idx} of the
+generalized vector @var{v} to @var{val}.
+@end deffn
 
+@deffn {Scheme Procedure} generalized-vector->list v
+@deffnx {C Function} scm_generalized_vector_to_list (v)
+Return a new list whose elements are the elements of the
+generalized vector @var{v}.
+@end deffn
 
-@node  Vtables
-@subsubsection Vtables
+@deftypefn {C Function} int scm_is_generalized_vector (SCM obj)
+Return @code{1} if @var{obj} is a vector, string,
+bitvector, or uniform numeric vector; else return @code{0}.
+@end deftypefn
 
-Vtables are structures that are used to represent structure types.  Each
-vtable contains a layout specification in field
-@code{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
-@code{vtable-offset-user} is bound to a field number.  Vtable fields
-at that position or greater are user definable.
+@deftypefn {C Function} size_t scm_c_generalized_vector_length (SCM v)
+Return the length of the generalized vector @var{v}.
+@end deftypefn
 
-@deffn {Scheme Procedure} struct-vtable handle
-@deffnx {C Function} scm_struct_vtable (handle)
-Return the vtable structure that describes the type of @var{struct}.
-@end deffn
+@deftypefn {C Function} SCM scm_c_generalized_vector_ref (SCM v, size_t idx)
+Return the element at index @var{idx} of the generalized vector @var{v}.
+@end deftypefn
 
-@deffn {Scheme Procedure} struct-vtable? x
-@deffnx {C Function} scm_struct_vtable_p (x)
-Return @code{#t} iff @var{x} is a vtable structure.
-@end deffn
+@deftypefn {C Function} void scm_c_generalized_vector_set_x (SCM v, size_t idx, SCM val)
+Set the element at index @var{idx} of the generalized vector @var{v}
+to @var{val}.
+@end deftypefn
 
-If you have a vtable structure, @code{V}, you can create an instance of
-the type it describes by using @code{(make-struct V ...)}.  But where
-does @code{V} itself come from?  One possibility is that @code{V} is an
-instance of a user-defined vtable type, @code{V'}, so that @code{V} is
-created by using @code{(make-struct V' ...)}.  Another possibility is
-that @code{V} is an instance of the type it itself describes.  Vtable
-structures of the second sort are created by this procedure:
+@deftypefn {C Function} void scm_generalized_vector_get_handle (SCM v, scm_t_array_handle *handle)
+Like @code{scm_array_get_handle} but an error is signalled when @var{v}
+is not of rank one.  You can use @code{scm_array_handle_ref} and
+@code{scm_array_handle_set} to read and write the elements of @var{v},
+or you can use functions like @code{scm_array_handle_<foo>_elements} to
+deal with specific types of vectors.
+@end deftypefn
 
-@deffn {Scheme Procedure} make-vtable-vtable user_fields tail_array_size . init
-@deffnx {C Function} scm_make_vtable_vtable (user_fields, tail_array_size, init)
-Return a new, self-describing vtable structure.
+@node Arrays
+@subsection Arrays
+@tpindex Arrays
 
-@var{user-fields} is a string describing user defined fields of the
-vtable beginning at index @code{vtable-offset-user}
-(see @code{make-struct-layout}).
+@dfn{Arrays} are a collection of cells organized into an arbitrary
+number of dimensions.  Each cell can be accessed in constant time by
+supplying an index for each dimension.
+
+In the current implementation, an array uses a generalized vector for
+the actual storage of its elements.  Any kind of generalized vector
+will do, so you can have arrays of uniform numeric values, arrays of
+characters, arrays of bits, and of course, arrays of arbitrary Scheme
+values.  For example, arrays with an underlying @code{c64vector} might
+be nice for digital signal processing, while arrays made from a
+@code{u8vector} might be used to hold gray-scale images.
+
+The number of dimensions of an array is called its @dfn{rank}.  Thus,
+a matrix is an array of rank 2, while a vector has rank 1.  When
+accessing an array element, you have to specify one exact integer for
+each dimension.  These integers are called the @dfn{indices} of the
+element.  An array specifies the allowed range of indices for each
+dimension via an inclusive lower and upper bound.  These bounds can
+well be negative, but the upper bound must be greater than or equal to
+the lower bound minus one.  When all lower bounds of an array are
+zero, it is called a @dfn{zero-origin} array.
+
+Arrays can be of rank 0, which could be interpreted as a scalar.
+Thus, a zero-rank array can store exactly one object and the list of
+indices of this element is the empty list.
+
+Arrays contain zero elements when one of their dimensions has a zero
+length.  These empty arrays maintain information about their shape: a
+matrix with zero columns and 3 rows is different from a matrix with 3
+columns and zero rows, which again is different from a vector of
+length zero.
+
+Generalized vectors, such as strings, uniform numeric vectors, bit
+vectors and ordinary vectors, are the special case of one dimensional
+arrays.
 
-@var{tail-size} specifies the size of the tail-array (if any) of
-this vtable.
+@menu
+* Array Syntax::                
+* Array Procedures::            
+* Shared Arrays::               
+* Accessing Arrays from C::     
+@end menu
 
-@var{init1}, @dots{} are the optional initializers for the fields of
-the vtable.
+@node Array Syntax
+@subsubsection Array Syntax
 
-Vtables have one initializable system field---the struct printer.
-This field comes before the user fields in the initializers passed
-to @code{make-vtable-vtable} and @code{make-struct}, and thus works as
-a third optional argument to @code{make-vtable-vtable} and a fourth to
-@code{make-struct} when creating vtables:
+An array is displayed as @code{#} followed by its rank, followed by a
+tag that describes the underlying vector, optionally followed by
+information about its shape, and finally followed by the cells,
+organized into dimensions using parentheses.
 
-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.
+In more words, the array tag is of the form
 
-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.
+@example
+  #<rank><vectag><@@lower><:len><@@lower><:len>...
+@end example
 
-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.)
+where @code{<rank>} is a positive integer in decimal giving the rank of
+the array.  It is omitted when the rank is 1 and the array is non-shared
+and has zero-origin (see below).  For shared arrays and for a non-zero
+origin, the rank is always printed even when it is 1 to dinstinguish
+them from ordinary vectors.
 
-@lisp
-(define ball-root (make-vtable-vtable "pr" 0))
+The @code{<vectag>} part is the tag for a uniform numeric vector, like
+@code{u8}, @code{s16}, etc, @code{b} for bitvectors, or @code{a} for
+strings.  It is empty for ordinary vectors.
 
-(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))
+The @code{<@@lower>} part is a @samp{@@} character followed by a signed
+integer in decimal giving the lower bound of a dimension.  There is one
+@code{<@@lower>} for each dimension.  When all lower bounds are zero,
+all @code{<@@lower>} parts are omitted.
 
-(define red (make-ball-type 'red))
-(define green (make-ball-type 'green))
+The @code{<:len>} part is a @samp{:} character followed by an unsigned
+integer in decimal giving the length of a dimension.  Like for the lower
+bounds, there is one @code{<:len>} for each dimension, and the
+@code{<:len>} part always follows the @code{<@@lower>} part for a
+dimension.  Lengths are only then printed when they can't be deduced
+from the nested lists of elements of the array literal, which can happen
+when at least one length is zero.
 
-(define (make-ball type owner) (make-struct type 0 owner))
+As a special case, an array of rank 0 is printed as
+@code{#0<vectag>(<scalar>)}, where @code{<scalar>} is the result of
+printing the single element of the array.
 
-(define ball (make-ball green 'Nisse))
-ball @result{} #<a green ball owned by Nisse>
-@end lisp
-@end deffn
+Thus, 
 
-@deffn {Scheme Procedure} struct-vtable-name vtable
-@deffnx {C Function} scm_struct_vtable_name (vtable)
-Return the name of the vtable @var{vtable}.
-@end deffn
+@table @code
+@item #(1 2 3)
+is an ordinary array of rank 1 with lower bound 0 in dimension 0.
+(I.e., a regular vector.)
 
-@deffn {Scheme Procedure} set-struct-vtable-name! vtable name
-@deffnx {C Function} scm_set_struct_vtable_name_x (vtable, name)
-Set the name of the vtable @var{vtable} to @var{name}.
-@end deffn
+@item #@@2(1 2 3)
+is an ordinary array of rank 1 with lower bound 2 in dimension 0.
 
-@deffn {Scheme Procedure} struct-vtable-tag handle
-@deffnx {C Function} scm_struct_vtable_tag (handle)
-Return the vtable tag of the structure @var{handle}.
-@end deffn
+@item #2((1 2 3) (4 5 6))
+is a non-uniform array of rank 2; a 3@cross{}3 matrix with index ranges 0..2
+and 0..2.
 
+@item #u32(0 1 2)
+is a uniform u8 array of rank 1.
 
-@node Arrays
-@subsection Arrays
-@tpindex Arrays
+@item #2u32@@2@@3((1 2) (2 3))
+is a uniform u8 array of rank 2 with index ranges 2..3 and 3..4.
 
-@menu
-* Conventional Arrays::         Arrays with arbitrary data.
-* Array Mapping::               Applying a procedure to the contents of an array.
-* Uniform Arrays::              Arrays with data of a single type.
-* Bit Vectors::                 Vectors of bits.
-@end menu
+@item #2()
+is a two-dimensional array with index ranges 0..-1 and 0..-1, i.e. both
+dimensions have length zero.
 
-@node Conventional Arrays
-@subsubsection Conventional Arrays
+@item #2:0:2()
+is a two-dimensional array with index ranges 0..-1 and 0..1, i.e. the
+first dimension has length zero, but the second has length 2.
 
-@dfn{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.
+@item #0(12)
+is a rank-zero array with contents 12.
 
-This contrasts with uniform arrays, which use memory more efficiently
-but can hold data of only a single type.  It contrasts also with lists
-where inserting and deleting cells is more efficient, but more time is
-usually required to access a particular cell.
+@end table
 
-A conventional array is displayed as @code{#} followed by the @dfn{rank}
-(number of dimensions) followed by the cells, organized into dimensions
-using parentheses.  The nesting depth of the parentheses is equal to
-the rank.
+@node Array Procedures
+@subsubsection Array Procedures
 
 When an array is created, the range of each dimension must be
 specified, e.g., to create a 2@cross{}3 array with a zero-based index:
@@ -1214,47 +1831,96 @@ way to create the same array:
 (make-array 'ho '(0 1) '(0 2)) @result{} #2((ho ho ho) (ho ho ho))
 @end example
 
-A conventional array with one dimension based at zero is identical to
-a vector:
-
-@example
-(make-array 'ho 3) @result{} #(ho ho ho)
-@end example
-
-The following procedures can be used with conventional arrays (or
-vectors).  An argument shown as @var{idx}@dots{} means one parameter
-for each dimension in the array.  Or a @var{idxlist} is a list of such
+The following procedures can be used with arrays (or vectors).  An
+argument shown as @var{idx}@dots{} means one parameter for each
+dimension in the array.  A @var{idxlist} argument means a list of such
 values, one for each dimension.
 
-@deffn {Scheme Procedure} array? obj [prot]
-@deffnx {C Function} scm_array_p (obj, prot)
+
+@deffn {Scheme Procedure} array? obj
+@deffnx {C Function} scm_array_p (obj, unused)
 Return @code{#t} if the @var{obj} is an array, and @code{#f} if
 not.
 
-The @var{prot} argument is used with uniform arrays (@pxref{Uniform
-Arrays}).  If given then the return is @code{#t} if @var{obj} is an
-array and of that prototype.
+The second argument to scm_array_p is there for historical reasons,
+but it is not used.  You should always pass @code{SCM_UNDEFINED} as
+its value.
+@end deffn
+
+@deffn {Scheme Procedure} typed-array? obj type
+@deffnx {C Function} scm_typed_array_p (obj, type)
+Return @code{#t} if the @var{obj} is an array of type @var{type}, and
+@code{#f} if not.
+@end deffn
+
+@deftypefn {C Function} int scm_is_array (SCM obj)
+Return @code{1} if the @var{obj} is an array and @code{0} if not.
+@end deftypefn
+
+@deftypefn {C Function} int scm_is_typed_array (SCM obj, SCM type)
+Return @code{0} if the @var{obj} is an array of type @var{type}, and
+@code{1} if not.
+@end deftypefn
+
+@deffn {Scheme Procedure} make-array fill bound @dots{}
+@deffnx {C Function} scm_make_array (fill, bounds)
+Equivalent to @code{(make-typed-array #t @var{fill} @var{bound} ...)}.
 @end deffn
 
-@deffn {Scheme Procedure} make-array initial-value bound @dots{}
+@deffn {Scheme Procedure} make-typed-array type fill bound @dots{}
+@deffnx {C Function} scm_make_typed_array (type, fill, bounds)
 Create and return an array that has as many dimensions as there are
-@var{bound}s and fill it with @var{initial-value}.
+@var{bound}s and (maybe) fill it with @var{fill}.
+
+The underlaying storage vector is created according to @var{type},
+which must be a symbol whose name is the `vectag' of the array as
+explained above, or @code{#t} for ordinary, non-specialized arrays.
+
+For example, using the symbol @code{f64} for @var{type} will create an
+array that uses a @code{f64vector} for storing its elements, and
+@code{a} will use a string.
+
+When @var{fill} is not the special @emph{unspecified} value, the new
+array is filled with @var{fill}.  Otherwise, the initial contents of
+the array is unspecified.  The special @emph{unspecified} value is
+stored in the variable @code{*unspecified*} so that for example
+@code{(make-typed-array 'u32 *unspecified* 4)} creates a uninitialized
+@code{u32} vector of length 4.
+
+Each @var{bound} may be a positive non-zero integer @var{N}, in which
+case the index for that dimension can range from 0 through @var{N-1}; or
+an explicit index range specifier in the form @code{(LOWER UPPER)},
+where both @var{lower} and @var{upper} are integers, possibly less than
+zero, and possibly the same number (however, @var{lower} cannot be
+greater than @var{upper}).
+@end deffn
 
-Each @var{bound}
-may be a positive non-zero integer @var{N}, in which case the index for
-that dimension can range from 0 through @var{N-1}; or an explicit index
-range specifier in the form @code{(LOWER UPPER)}, where both @var{lower}
-and @var{upper} are integers, possibly less than zero, and possibly the
-same number (however, @var{lower} cannot be greater than @var{upper}).
-See examples above.
+@deffn {Scheme Procedure} list->array dimspec list
+Equivalent to @code{(list->typed-array #t @var{dimspec}
+@var{list})}.
 @end deffn
 
-@c array-ref's type is `compiled-closure'.  There's some weird stuff
-@c going on in array.c, too.  Let's call it a primitive. -twp
+@deffn {Scheme Procedure} list->typed-array type dimspec list
+@deffnx {C Function} scm_list_to_typed_array (type, dimspec, list)
+Return an array of the type indicated by @var{type} with elements the
+same as those of @var{list}.
+
+The argument @var{dimspec} determines the number of dimensions of the
+array and their lower bounds.  When @var{dimspec} is an exact integer,
+it gives the number of dimensions directly and all lower bounds are
+zero.  When it is a list of exact integers, then each element is the
+lower index bound of a dimension, and there will be as many dimensions
+as elements in the list.
+@end deffn
+
+@deffn {Scheme Procedure} array-type array
+Return the type of @var{array}.  This is the `vectag' used for
+printing @var{array} (or @code{#t} for ordinary arrays) and can be
+used with @code{make-typed-array} to create an array of the same kind
+as @var{array}.
+@end deffn
 
 @deffn {Scheme Procedure} array-ref array idx @dots{}
-@deffnx {Scheme Procedure} uniform-vector-ref vec args
-@deffnx {C Function} scm_uniform_vector_ref (vec, args)
 Return the element at @code{(idx @dots{})} in @var{array}.
 
 @example
@@ -1270,14 +1936,12 @@ Return @code{#t} if the given index would be acceptable to
 
 @example
 (define a (make-array #f '(1 2) '(3 4)))
-(array-in-bounds? a 2 3) @result{} #f
+(array-in-bounds? a 2 3) @result{} #t
 (array-in-bounds? a 0 0) @result{} #f
 @end example
 @end deffn
 
-@c fixme: why do these sigs differ?  -ttn 2001/07/19 01:14:12
 @deffn {Scheme Procedure} array-set! array obj idx @dots{}
-@deffnx {Scheme Procedure} uniform-array-set1! array obj idxlist
 @deffnx {C Function} scm_array_set_x (array, obj, idxlist)
 Set the element at @code{(idx @dots{})} in @var{array} to @var{obj}.
 The return value is unspecified.
@@ -1289,64 +1953,6 @@ a @result{} #2((#f #f) (#f #t))
 @end example
 @end deffn
 
-@deffn {Scheme Procedure} make-shared-array oldarray mapfunc bound @dots{}
-@deffnx {C Function} scm_make_shared_array (oldarray, mapfunc, boundlist)
-@code{make-shared-array} can be used to create shared subarrays of other
-arrays.  The @var{mapper} is a function that translates coordinates in
-the new array into coordinates in the old array.  A @var{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:
-
-@lisp
-(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) @result{} foo
-(define freds-center
-  (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))
-(array-ref freds-center 0 0) @result{} foo
-@end lisp
-@end deffn
-
-@deffn {Scheme Procedure} shared-array-increments array
-@deffnx {C Function} scm_shared_array_increments (array)
-For each dimension, return the distance between elements in the root vector.
-@end deffn
-
-@deffn {Scheme Procedure} shared-array-offset array
-@deffnx {C Function} scm_shared_array_offset (array)
-Return the root vector index of the first element in the array.
-@end deffn
-
-@deffn {Scheme Procedure} shared-array-root array
-@deffnx {C Function} scm_shared_array_root (array)
-Return the root vector of a shared array.
-@end deffn
-
-@deffn {Scheme Procedure} transpose-array array dim1 @dots{}
-@deffnx {C Function} scm_transpose_array (array, dimlist)
-Return an array sharing contents with @var{array}, but with
-dimensions arranged in a different order.  There must be one
-@var{dim} argument for each dimension of @var{array}.
-@var{dim1}, @var{dim2}, @dots{} 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 @var{dim1}, @var{dim2}, @dots{} correspond to
-dimensions in the array to be returned, and their positions in the
-argument list to dimensions of @var{array}.  Several @var{dim}s
-may have the same value, in which case the returned array will
-have smaller rank than @var{array}.
-
-@lisp
-(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))
-(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)
-(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}
-                #2((a 4) (b 5) (c 6))
-@end lisp
-@end deffn
-
 @deffn {Scheme Procedure} enclose-array array dim1 @dots{}
 @deffnx {C Function} scm_enclose_array (array, dimlist)
 @var{dim1}, @var{dim2} @dots{} should be nonnegative integers less than
@@ -1396,10 +2002,13 @@ For example,
 
 @deffn {Scheme Procedure} array-rank obj
 @deffnx {C Function} scm_array_rank (obj)
-Return the number of dimensions of an array @var{obj}, or if @var{obj}
-is not an array then return 0.
+Return the rank of @var{array}.
 @end deffn
 
+@deftypefn {C Function} size_t scm_c_array_rank (SCM array)
+Return the rank of @var{array} as a @code{size_t}.
+@end deftypefn
+
 @deffn {Scheme Procedure} array->list array
 @deffnx {C Function} scm_array_to_list (array)
 Return a list consisting of all the elements, in order, of
@@ -1429,27 +2038,11 @@ is unspecified.
 Return @code{#t} if all arguments are arrays with the same shape, the
 same type, and have corresponding elements which are either
 @code{equal?} or @code{array-equal?}.  This function differs from
-@code{equal?} in that a one dimensional shared array may be
-@var{array-equal?} but not @var{equal?} to a vector or uniform vector.
+@code{equal?} (@pxref{Equality}) in that a one dimensional shared
+array may be @code{array-equal?} but not @code{equal?} to a vector or
+uniform vector.
 @end deffn
 
-@deffn {Scheme Procedure} array-contents array [strict]
-@deffnx {C Function} scm_array_contents (array, strict)
-If @var{array} may be @dfn{unrolled} into a one dimensional shared array
-without changing their order (last subscript changing fastest), then
-@code{array-contents} returns that shared array, otherwise it returns
-@code{#f}.  All arrays made by @code{make-array} and
-@code{make-uniform-array} may be unrolled, some arrays made by
-@code{make-shared-array} may not be.
-
-If the optional argument @var{strict} is provided, a shared array will
-be returned only if its elements are stored internally contiguous in
-memory.
-@end deffn
-
-@node Array Mapping
-@subsubsection Array Mapping
-
 @c  FIXME: array-map! accepts no source arrays at all, and in that
 @c  case makes calls "(proc)".  Is that meant to be a documented
 @c  feature?
@@ -1520,236 +2113,899 @@ $\left(\matrix{%
 @end example
 @end deffn
 
-@node Uniform Arrays
-@subsubsection Uniform Arrays
-@tpindex Uniform Arrays
+@deffn {Scheme Procedure} uniform-array-read! ra [port_or_fd [start [end]]]
+@deffnx {C Function} scm_uniform_array_read_x (ra, port_or_fd, start, end)
+Attempt to read all elements of @var{ura}, in lexicographic order, as
+binary objects from @var{port-or-fdes}.
+If an end of file is encountered,
+the objects up to that point are put into @var{ura}
+(starting at the beginning) and the remainder of the array is
+unchanged.
+
+The optional arguments @var{start} and @var{end} allow
+a specified region of a vector (or linearized array) to be read,
+leaving the remainder of the vector unchanged.
+
+@code{uniform-array-read!} returns the number of objects read.
+@var{port-or-fdes} may be omitted, in which case it defaults to the value
+returned by @code{(current-input-port)}.
+@end deffn
+
+@deffn {Scheme Procedure} uniform-array-write v [port_or_fd [start [end]]]
+@deffnx {C Function} scm_uniform_array_write (v, port_or_fd, start, end)
+Writes all elements of @var{ura} as binary objects to
+@var{port-or-fdes}.
+
+The optional arguments @var{start}
+and @var{end} allow
+a specified region of a vector (or linearized array) to be written.
+
+The number of objects actually written is returned.
+@var{port-or-fdes} may be
+omitted, in which case it defaults to the value returned by
+@code{(current-output-port)}.
+@end deffn
+
+@node Shared Arrays
+@subsubsection Shared Arrays
+
+@deffn {Scheme Procedure} make-shared-array oldarray mapfunc bound @dots{}
+@deffnx {C Function} scm_make_shared_array (oldarray, mapfunc, boundlist)
+Return a new array which shares the storage of @var{oldarray}.
+Changes made through either affect the same underlying storage.  The
+@var{bound@dots{}} arguments are the shape of the new array, the same
+as @code{make-array} (@pxref{Array Procedures}).
+
+@var{mapfunc} translates coordinates from the new array to the
+@var{oldarray}.  It's called as @code{(@var{mapfunc} newidx1 @dots{})}
+with one parameter for each dimension of the new array, and should
+return a list of indices for @var{oldarray}, one for each dimension of
+@var{oldarray}.
+
+@var{mapfunc} must be affine linear, meaning that each @var{oldarray}
+index must be formed by adding integer multiples (possibly negative)
+of some or all of @var{newidx1} etc, plus a possible integer offset.
+The multiples and offset must be the same in each call.
+
+@sp 1
+One good use for a shared array is to restrict the range of some
+dimensions, so as to apply say @code{array-for-each} or
+@code{array-fill!} to only part of an array.  The plain @code{list}
+function can be used for @var{mapfunc} in this case, making no changes
+to the index values.  For example,
+
+@example
+(make-shared-array #2((a b c) (d e f) (g h i)) list 3 2)
+@result{} #2((a b) (d e) (g h))
+@end example
+
+The new array can have fewer dimensions than @var{oldarray}, for
+example to take a column from an array.
+
+@example
+(make-shared-array #2((a b c) (d e f) (g h i))
+                   (lambda (i) (list i 2))
+                   '(0 2))
+@result{} #1(c f i)
+@end example
+
+A diagonal can be taken by using the single new array index for both
+row and column in the old array.  For example,
+
+@example
+(make-shared-array #2((a b c) (d e f) (g h i))
+                   (lambda (i) (list i i))
+                   '(0 2))
+@result{} #1(a e i)
+@end example
+
+Dimensions can be increased by for instance considering portions of a
+one dimensional array as rows in a two dimensional array.
+(@code{array-contents} below can do the opposite, flattening an
+array.)
+
+@example
+(make-shared-array #1(a b c d e f g h i j k l)
+                   (lambda (i j) (list (+ (* i 3) j)))
+                   4 3)
+@result{} #2((a b c) (d e f) (g h i) (j k l))
+@end example
+
+By negating an index the order that elements appear can be reversed.
+The following just reverses the column order,
+
+@example
+(make-shared-array #2((a b c) (d e f) (g h i))
+                   (lambda (i j) (list i (- 2 j)))
+                   3 3)
+@result{} #2((c b a) (f e d) (i h g))
+@end example
+
+A fixed offset on indexes allows for instance a change from a 0 based
+to a 1 based array,
+
+@example
+(define x #2((a b c) (d e f) (g h i)))
+(define y (make-shared-array x
+                             (lambda (i j) (list (1- i) (1- j)))
+                             '(1 3) '(1 3)))
+(array-ref x 0 0) @result{} a
+(array-ref y 1 1) @result{} a
+@end example
+
+A multiple on an index allows every Nth element of an array to be
+taken.  The following is every third element,
+
+@example
+(make-shared-array #1(a b c d e f g h i j k l)
+                   (lambda (i) (list (* i 3)))
+                   4)
+@result{} #1(a d g j)
+@end example
+
+The above examples can be combined to make weird and wonderful
+selections from an array, but it's important to note that because
+@var{mapfunc} must be affine linear, arbitrary permutations are not
+possible.
+
+In the current implementation, @var{mapfunc} is not called for every
+access to the new array but only on some sample points to establish a
+base and stride for new array indices in @var{oldarray} data.  A few
+sample points are enough because @var{mapfunc} is linear.
+@end deffn
+
+@deffn {Scheme Procedure} shared-array-increments array
+@deffnx {C Function} scm_shared_array_increments (array)
+For each dimension, return the distance between elements in the root vector.
+@end deffn
+
+@deffn {Scheme Procedure} shared-array-offset array
+@deffnx {C Function} scm_shared_array_offset (array)
+Return the root vector index of the first element in the array.
+@end deffn
+
+@deffn {Scheme Procedure} shared-array-root array
+@deffnx {C Function} scm_shared_array_root (array)
+Return the root vector of a shared array.
+@end deffn
+
+@deffn {Scheme Procedure} array-contents array [strict]
+@deffnx {C Function} scm_array_contents (array, strict)
+If @var{array} may be @dfn{unrolled} into a one dimensional shared array
+without changing their order (last subscript changing fastest), then
+@code{array-contents} returns that shared array, otherwise it returns
+@code{#f}.  All arrays made by @code{make-array} and
+@code{make-typed-array} may be unrolled, some arrays made by
+@code{make-shared-array} may not be.
+
+If the optional argument @var{strict} is provided, a shared array will
+be returned only if its elements are stored internally contiguous in
+memory.
+@end deffn
+
+@deffn {Scheme Procedure} transpose-array array dim1 @dots{}
+@deffnx {C Function} scm_transpose_array (array, dimlist)
+Return an array sharing contents with @var{array}, but with
+dimensions arranged in a different order.  There must be one
+@var{dim} argument for each dimension of @var{array}.
+@var{dim1}, @var{dim2}, @dots{} 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 @var{dim1}, @var{dim2}, @dots{} correspond to
+dimensions in the array to be returned, and their positions in the
+argument list to dimensions of @var{array}.  Several @var{dim}s
+may have the same value, in which case the returned array will
+have smaller rank than @var{array}.
+
+@lisp
+(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))
+(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)
+(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}
+                #2((a 4) (b 5) (c 6))
+@end lisp
+@end deffn
+
+@node Accessing Arrays from C
+@subsubsection Accessing Arrays from C
+
+Arrays, especially uniform numeric arrays, are useful to efficiently
+represent large amounts of rectangularily organized information, such as
+matrices, images, or generally blobs of binary data.  It is desirable to
+access these blobs in a C like manner so that they can be handed to
+external C code such as linear algebra libraries or image processing
+routines.
+
+While pointers to the elements of an array are in use, the array itself
+must be protected so that the pointer remains valid.  Such a protected
+array is said to be @dfn{reserved}.  A reserved array can be read but
+modifications to it that would cause the pointer to its elements to
+become invalid are prevented.  When you attempt such a modification, an
+error is signalled.
+
+(This is similar to locking the array while it is in use, but without
+the danger of a deadlock.  In a multi-threaded program, you will need
+additional synchronization to avoid modifying reserved arrays.)
+
+You must take care to always unreserve an array after reserving it,
+also in the presence of non-local exits.  To simplify this, reserving
+and unreserving work like a dynwind context (@pxref{Dynamic Wind}): a
+call to @code{scm_array_get_handle} can be thought of as beginning a
+dynwind context and @code{scm_array_handle_release} as ending it.
+When a non-local exit happens between these two calls, the array is
+implicitely unreserved.
+
+That is, you need to properly pair reserving and unreserving in your
+code, but you don't need to worry about non-local exits.
+
+These calls and other pairs of calls that establish dynwind contexts
+need to be properly nested.  If you begin a context prior to reserving
+an array, you need to unreserve the array before ending the context.
+Likewise, when reserving two or more arrays in a certain order, you
+need to unreserve them in the opposite order.
+
+Once you have reserved an array and have retrieved the pointer to its
+elements, you must figure out the layout of the elements in memory.
+Guile allows slices to be taken out of arrays without actually making a
+copy, such as making an alias for the diagonal of a matrix that can be
+treated as a vector.  Arrays that result from such an operation are not
+stored contiguously in memory and when working with their elements
+directly, you need to take this into account.
+
+The layout of array elements in memory can be defined via a
+@emph{mapping function} that computes a scalar position from a vector of
+indices.  The scalar position then is the offset of the element with the
+given indices from the start of the storage block of the array.
+
+In Guile, this mapping function is restricted to be @dfn{affine}: all
+mapping functions of Guile arrays can be written as @code{p = b +
+c[0]*i[0] + c[1]*i[1] + ... + c[n-1]*i[n-1]} where @code{i[k]} is the
+@nicode{k}th index and @code{n} is the rank of the array.  For
+example, a matrix of size 3x3 would have @code{b == 0}, @code{c[0] ==
+3} and @code{c[1] == 1}.  When you transpose this matrix (with
+@code{transpose-array}, say), you will get an array whose mapping
+function has @code{b == 0}, @code{c[0] == 1} and @code{c[1] == 3}.
+
+The function @code{scm_array_handle_dims} gives you (indirect) access to
+the coefficients @code{c[k]}.
+
+@c XXX
+Note that there are no functions for accessing the elements of a
+character array yet.  Once the string implementation of Guile has been
+changed to use Unicode, we will provide them.
+
+@deftp {C Type} scm_t_array_handle
+This is a structure type that holds all information necessary to manage
+the reservation of arrays as explained above.  Structures of this type
+must be allocated on the stack and must only be accessed by the
+functions listed below.
+@end deftp
+
+@deftypefn {C Function} void scm_array_get_handle (SCM array, scm_t_array_handle *handle)
+Reserve @var{array}, which must be an array, and prepare @var{handle} to
+be used with the functions below.  You must eventually call
+@code{scm_array_handle_release} on @var{handle}, and do this in a
+properly nested fashion, as explained above.  The structure pointed to
+by @var{handle} does not need to be initialized before calling this
+function.
+@end deftypefn
+
+@deftypefn {C Function} void scm_array_handle_release (scm_t_array_handle *handle)
+End the array reservation represented by @var{handle}.  After a call to
+this function, @var{handle} might be used for another reservation.
+@end deftypefn
+
+@deftypefn {C Function} size_t scm_array_handle_rank (scm_t_array_handle *handle)
+Return the rank of the array represented by @var{handle}.
+@end deftypefn
+
+@deftp {C Type} scm_t_array_dim
+This structure type holds information about the layout of one dimension
+of an array.  It includes the following fields:
+
+@table @code
+@item  ssize_t lbnd
+@itemx ssize_t ubnd
+The lower and upper bounds (both inclusive) of the permissible index
+range for the given dimension.  Both values can be negative, but
+@var{lbnd} is always less than or equal to @var{ubnd}.
+
+@item ssize_t inc
+The distance from one element of this dimension to the next.  Note, too,
+that this can be negative.
+@end table
+@end deftp
+
+@deftypefn {C Function} {const scm_t_array_dim *} scm_array_handle_dims (scm_t_array_handle *handle)
+Return a pointer to a C vector of information about the dimensions of
+the array represented by @var{handle}.  This pointer is valid as long as
+the array remains reserved.  As explained above, the
+@code{scm_t_array_dim} structures returned by this function can be used
+calculate the position of an element in the storage block of the array
+from its indices.
+
+This position can then be used as an index into the C array pointer
+returned by the various @code{scm_array_handle_<foo>_elements}
+functions, or with @code{scm_array_handle_ref} and
+@code{scm_array_handle_set}.
+
+Here is how one can compute the position @var{pos} of an element given
+its indices in the vector @var{indices}:
+
+@example
+ssize_t indices[RANK];
+scm_t_array_dim *dims;
+ssize_t pos;
+size_t i;
+
+pos = 0;
+for (i = 0; i < RANK; i++)
+  @{
+    if (indices[i] < dims[i].lbnd || indices[i] > dims[i].ubnd)
+      out_of_range ();
+    pos += (indices[i] - dims[i].lbnd) * dims[i].inc;
+  @}
+@end example
+@end deftypefn
+
+@deftypefn {C Function} ssize_t scm_array_handle_pos (scm_t_array_handle *handle, SCM indices)
+Compute the position corresponding to @var{indices}, a list of
+indices.  The position is computed as described above for
+@code{scm_array_handle_dims}.  The number of the indices and their
+range is checked and an approrpiate error is signalled for invalid
+indices.
+@end deftypefn
+
+@deftypefn {C Function} SCM scm_array_handle_ref (scm_t_array_handle *handle, ssize_t pos)
+Return the element at position @var{pos} in the storage block of the
+array represented by @var{handle}.  Any kind of array is acceptable.  No
+range checking is done on @var{pos}.
+@end deftypefn
+
+@deftypefn {C Function} void scm_array_handle_set (scm_t_array_handle *handle, ssize_t pos, SCM val)
+Set the element at position @var{pos} in the storage block of the array
+represented by @var{handle} to @var{val}.  Any kind of array is
+acceptable.  No range checking is done on @var{pos}.  An error is
+signalled when the array can not store @var{val}.
+@end deftypefn
+
+@deftypefn {C Function} {const SCM *} scm_array_handle_elements (scm_t_array_handle *handle)
+Return a pointer to the elements of a ordinary array of general Scheme
+values (i.e., a non-uniform array) for reading.  This pointer is valid
+as long as the array remains reserved.
+@end deftypefn
+
+@deftypefn {C Function} {SCM *} scm_array_handle_writable_elements (scm_t_array_handle *handle)
+Like @code{scm_array_handle_elements}, but the pointer is good for
+reading and writing.
+@end deftypefn
+
+@deftypefn {C Function} {const void *} scm_array_handle_uniform_elements (scm_t_array_handle *handle)
+Return a pointer to the elements of a uniform numeric array for reading.
+This pointer is valid as long as the array remains reserved.  The size
+of each element is given by @code{scm_array_handle_uniform_element_size}.
+@end deftypefn
+
+@deftypefn {C Function} {void *} scm_array_handle_uniform_writable_elements (scm_t_array_handle *handle)
+Like @code{scm_array_handle_uniform_elements}, but the pointer is good
+reading and writing.
+@end deftypefn
+
+@deftypefn {C Function} size_t scm_array_handle_uniform_element_size (scm_t_array_handle *handle)
+Return the size of one element of the uniform numeric array represented
+by @var{handle}.
+@end deftypefn
+
+@deftypefn  {C Function} {const scm_t_uint8 *} scm_array_handle_u8_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_int8 *} scm_array_handle_s8_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_uint16 *} scm_array_handle_u16_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_int16 *} scm_array_handle_s16_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_uint32 *} scm_array_handle_u32_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_int32 *} scm_array_handle_s32_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_uint64 *} scm_array_handle_u64_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const scm_t_int64 *} scm_array_handle_s64_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const float *} scm_array_handle_f32_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const double *} scm_array_handle_f64_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const float *} scm_array_handle_c32_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {const double *} scm_array_handle_c64_elements (scm_t_array_handle *handle)
+Return a pointer to the elements of a uniform numeric array of the
+indicated kind for reading.  This pointer is valid as long as the array
+remains reserved.
+
+The pointers for @code{c32} and @code{c64} uniform numeric arrays point
+to pairs of floating point numbers.  The even index holds the real part,
+the odd index the imaginary part of the complex number.
+@end deftypefn
+
+@deftypefn {C Function} {scm_t_uint8 *} scm_array_handle_u8_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_int8 *} scm_array_handle_s8_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_uint16 *} scm_array_handle_u16_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_int16 *} scm_array_handle_s16_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_uint32 *} scm_array_handle_u32_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_int32 *} scm_array_handle_s32_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_uint64 *} scm_array_handle_u64_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {scm_t_int64 *} scm_array_handle_s64_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {float *} scm_array_handle_f32_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {double *} scm_array_handle_f64_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {float *} scm_array_handle_c32_writable_elements (scm_t_array_handle *handle)
+@deftypefnx {C Function} {double *} scm_array_handle_c64_writable_elements (scm_t_array_handle *handle)
+Like @code{scm_array_handle_<kind>_elements}, but the pointer is good
+for reading and writing.
+@end deftypefn
+
+@deftypefn {C Function} {const scm_t_uint32 *} scm_array_handle_bit_elements (scm_t_array_handle *handle)
+Return a pointer to the words that store the bits of the represented
+array, which must be a bit array.
+
+Unlike other arrays, bit arrays have an additional offset that must be
+figured into index calculations.  That offset is returned by
+@code{scm_array_handle_bit_elements_offset}.
+
+To find a certain bit you first need to calculate its position as
+explained above for @code{scm_array_handle_dims} and then add the
+offset.  This gives the absolute position of the bit, which is always a
+non-negative integer.
+
+Each word of the bit array storage block contains exactly 32 bits, with
+the least significant bit in that word having the lowest absolute
+position number.  The next word contains the next 32 bits.
+
+Thus, the following code can be used to access a bit whose position
+according to @code{scm_array_handle_dims} is given in @var{pos}:
+
+@example
+SCM bit_array;
+scm_t_array_handle handle;
+scm_t_uint32 *bits;
+ssize_t pos;
+size_t abs_pos;
+size_t word_pos, mask;
+
+scm_array_get_handle (&bit_array, &handle);
+bits = scm_array_handle_bit_elements (&handle);
+
+pos = ...
+abs_pos = pos + scm_array_handle_bit_elements_offset (&handle);
+word_pos = abs_pos / 32;
+mask = 1L << (abs_pos % 32);
+
+if (bits[word_pos] & mask)
+  /* bit is set. */
+
+scm_array_handle_release (&handle);
+@end example
+
+@end deftypefn
+
+@deftypefn {C Function} {scm_t_uint32 *} scm_array_handle_bit_writable_elements (scm_t_array_handle *handle)
+Like @code{scm_array_handle_bit_elements} but the pointer is good for
+reading and writing.  You must take care not to modify bits outside of
+the allowed index range of the array, even for contiguous arrays.
+@end deftypefn
+
+@node Records
+@subsection Records
+
+A @dfn{record type} is a first class object representing a user-defined
+data type.  A @dfn{record} is an instance of a record type.
+
+@deffn {Scheme Procedure} record? obj
+Return @code{#t} if @var{obj} is a record of any type and @code{#f}
+otherwise.
+
+Note that @code{record?} may be true of any Scheme value; there is no
+promise that records are disjoint with other Scheme types.
+@end deffn
+
+@deffn {Scheme Procedure} make-record-type type-name field-names
+Return a @dfn{record-type descriptor}, a value representing a new data
+type disjoint from all others.  The @var{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 @var{field-names}
+argument is a list of symbols naming the @dfn{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.
+@end deffn
+
+@deffn {Scheme Procedure} record-constructor rtd [field-names]
+Return a procedure for constructing new members of the type represented
+by @var{rtd}.  The returned procedure accepts exactly as many arguments
+as there are symbols in the given list, @var{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 @var{field-names}
+argument defaults to the list of field names in the call to
+@code{make-record-type} that created the type represented by @var{rtd};
+if the @var{field-names} argument is provided, it is an error if it
+contains any duplicates or any symbols not in the default list.
+@end deffn
+
+@deffn {Scheme Procedure} record-predicate rtd
+Return a procedure for testing membership in the type represented by
+@var{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.
+@end deffn
+
+@deffn {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 @var{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
+@var{field-name} in that record.  The symbol @var{field-name} must be a
+member of the list of field-names in the call to @code{make-record-type}
+that created the type represented by @var{rtd}.
+@end deffn
+
+@deffn {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 @var{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 @var{field-name} in that record to contain the given value.
+The returned value of the modifier procedure is unspecified.  The symbol
+@var{field-name} must be a member of the list of field-names in the call
+to @code{make-record-type} that created the type represented by
+@var{rtd}.
+@end deffn
+
+@deffn {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
+@code{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
+@code{record-constructor} in the call that created the constructor
+procedure that created the given record.
+@end deffn
+
+@deffn {Scheme Procedure} record-type-name rtd
+Return the type-name associated with the type represented by rtd.  The
+returned value is @code{eqv?} to the @var{type-name} argument given in
+the call to @code{make-record-type} that created the type represented by
+@var{rtd}.
+@end deffn
+
+@deffn {Scheme Procedure} record-type-fields rtd
+Return a list of the symbols naming the fields in members of the type
+represented by @var{rtd}.  The returned value is @code{equal?} to the
+field-names argument given in the call to @code{make-record-type} that
+created the type represented by @var{rtd}.
+@end deffn
+
+
+@node Structures
+@subsection Structures
+@tpindex Structures
+
+[FIXME: this is pasted in from Tom Lord's original guile.texi and should
+be reviewed]
+
+A @dfn{structure type} is a first class user-defined data type.  A
+@dfn{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.
+
+@menu
+* Structure Concepts::          The structure of Structures
+* Structure Layout::            Defining the layout of structure types
+* Structure Basics::            make-, -ref and -set! procedures for structs
+* Vtables::                     Accessing type-specific data
+@end menu
+
+@node  Structure Concepts
+@subsubsection 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.
+
+When applied to structures, the @code{equal?} predicate
+(@pxref{Equality}) returns @code{#t} if the two structures share a
+common vtable @emph{and} all their fields satisfy @code{equal?}.
+
+Three concepts are key to understanding structures.
+
+@itemize @bullet{}
+@item @dfn{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.
+
+@item @dfn{structural accessors}
+
+Structure access is by field number.   There is only one set of
+accessors common to all structure objects.
+
+@item @dfn{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.
+@end itemize
+
+
+
+@node  Structure Layout
+@subsubsection Structure Layout
+
+When a structure is created, a region of memory is allocated to hold its
+state.  The @dfn{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:
+
+@itemize @bullet{}
+@item 'u' -- unprotected
+
+The field holds binary data that is not GC protected.
+
+@item 'p' -- protected
+
+The field holds a Scheme value and is GC protected.
+
+@item '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.
+@end itemize
+
+
+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:
+
+@itemize @bullet{}
+@item 'w' -- writable
+
+The field can be read and written.
+
+@item 'r' -- readable
+
+The field can be read, but not written.
+
+@item 'o' -- opaque
+
+The field can be neither read nor written.   This kind
+of protection is for fields useful only to built-in routines.
+@end itemize
+
+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:
+
+@example
+; cons pairs have two writable fields of Scheme data
+"pwpw"
+@end example
+
+A pair object in which the first field is held constant could be:
+
+@example
+"prpw"
+@end example
+
+Binary fields, (fields of type "u"), hold one @dfn{word} each.  The
+size of a word is a machine dependent value defined to be equal to the
+value of the C expression: @code{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:
+
+@example
+; A vector is an arbitrary number of writable fields holding Scheme
+; values:
+"pW"
+@end example
+
+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:
+
+@example
+"prpW"
+@end example
+
+
+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:
+
+@deffn {Scheme Procedure} make-struct-layout fields
+@deffnx {C Function} scm_make_struct_layout (fields)
+Return a new structure layout object.
+
+@var{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.
+@end deffn
+
 
-@noindent
-@dfn{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 @dfn{uniform vectors}.  The procedures in
-this section can also be used on conventional arrays, vectors,
-bit-vectors and strings.
 
-@noindent
-When creating a uniform array, the type of data to be stored
-is indicated with a @var{prototype} argument.  The following table
-lists the types available and example prototypes:
+@node Structure Basics
+@subsubsection Structure Basics
 
-@example
-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
-@end example
+This section describes the basic procedures for creating and accessing
+structures.
 
-Note that with the introduction of exact fractions in Guile 1.8,
-@samp{1/3} here is now a fraction, where previously such an expression
-was a double @samp{0.333@dots{}}.  For most normal usages this should
-be source code compatible.
+@deffn {Scheme Procedure} make-struct vtable tail_array_size . init
+@deffnx {C Function} scm_make_struct (vtable, tail_array_size, init)
+Create a new structure.
 
-Unshared uniform arrays of characters with a single zero-based dimension
-are identical to strings:
+@var{type} must be a vtable structure (@pxref{Vtables}).
 
-@example
-(make-uniform-array #\a 3) @result{}
-"aaa"
-@end example
+@var{tail-elts} must be a non-negative integer.  If the layout
+specification indicated by @var{type} includes a tail-array,
+this is the number of elements allocated to that array.
 
-@noindent
-Unshared uniform arrays of booleans with a single zero-based dimension
-are identical to @ref{Bit Vectors, bit-vectors}.
+The @var{init1}, @dots{} 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.
 
-@example
-(make-uniform-array #t 3) @result{}
-#*111
-@end example
+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.
 
-@noindent
-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
-@code{#} and @code{(}.  For example, a uniform vector of signed
-long integers is displayed in the form @code{'#e(3 5 9)}.
+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.
 
-@deffn {Scheme Procedure} make-uniform-array prototype bound1 bound2 @dots{}
-Create and return a uniform array of type corresponding to
-@var{prototype} that has as many dimensions as there are @var{bound}s
-and fill it with @var{prototype}.
+For more information, see the documentation for @code{make-vtable-vtable}.
 @end deffn
 
-@deffn {Scheme Procedure} array-prototype ra
-@deffnx {C Function} scm_array_prototype (ra)
-Return an object that would produce an array of the same type
-as @var{array}, if used as the @var{prototype} for
-@code{make-uniform-array}.
+@deffn {Scheme Procedure} struct? x
+@deffnx {C Function} scm_struct_p (x)
+Return @code{#t} iff @var{x} is a structure object, else
+@code{#f}.
 @end deffn
 
-@deffn {Scheme Procedure} list->uniform-array ndim prot lst
-@deffnx {Scheme Procedure} list->uniform-vector prot lst
-@deffnx {C Function} scm_list_to_uniform_array (ndim, prot, lst)
-Return a uniform array of the type indicated by prototype
-@var{prot} with elements the same as those of @var{lst}.
-Elements must be of the appropriate type, no coercions are
-done.
-@end deffn
 
-@deffn {Scheme Procedure} uniform-vector-fill! uve fill
-Store @var{fill} in every element of @var{uve}.  The value returned is
-unspecified.
-@end deffn
+@deffn {Scheme Procedure} struct-ref handle pos
+@deffnx {Scheme Procedure} struct-set! struct n value
+@deffnx {C Function} scm_struct_ref (handle, pos)
+@deffnx {C Function} scm_struct_set_x (struct, n, value)
+Access (or modify) the @var{n}th field of @var{struct}.
 
-@deffn {Scheme Procedure} uniform-vector-length v
-@deffnx {C Function} scm_uniform_vector_length (v)
-Return the number of elements in @var{uve}.
-@end deffn
+If the field is of type 'p', then it can be set to an arbitrary value.
 
-@deffn {Scheme Procedure} dimensions->uniform-array dims prot [fill]
-@deffnx {Scheme Procedure} make-uniform-vector length prototype [fill]
-@deffnx {C Function} scm_dimensions_to_uniform_array (dims, prot, fill)
-Create and return a uniform array or vector of type
-corresponding to @var{prototype} with dimensions @var{dims} or
-length @var{length}.  If @var{fill} is supplied, it's used to
-fill the array, otherwise @var{prototype} is used.
+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.
 @end deffn
 
-@c Another compiled-closure. -twp
-
-@deffn {Scheme Procedure} uniform-array-read! ra [port_or_fd [start [end]]]
-@deffnx {Scheme Procedure} uniform-vector-read! uve [port-or-fdes] [start] [end]
-@deffnx {C Function} scm_uniform_array_read_x (ra, port_or_fd, start, end)
-Attempt to read all elements of @var{ura}, in lexicographic order, as
-binary objects from @var{port-or-fdes}.
-If an end of file is encountered,
-the objects up to that point are put into @var{ura}
-(starting at the beginning) and the remainder of the array is
-unchanged.
 
-The optional arguments @var{start} and @var{end} allow
-a specified region of a vector (or linearized array) to be read,
-leaving the remainder of the vector unchanged.
 
-@code{uniform-array-read!} returns the number of objects read.
-@var{port-or-fdes} may be omitted, in which case it defaults to the value
-returned by @code{(current-input-port)}.
-@end deffn
+@node  Vtables
+@subsubsection Vtables
 
-@deffn {Scheme Procedure} uniform-array-write v [port_or_fd [start [end]]]
-@deffnx {Scheme Procedure} uniform-vector-write uve [port-or-fdes] [start] [end]
-@deffnx {C Function} scm_uniform_array_write (v, port_or_fd, start, end)
-Writes all elements of @var{ura} as binary objects to
-@var{port-or-fdes}.
+Vtables are structures that are used to represent structure types.  Each
+vtable contains a layout specification in field
+@code{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
+@code{vtable-offset-user} is bound to a field number.  Vtable fields
+at that position or greater are user definable.
 
-The optional arguments @var{start}
-and @var{end} allow
-a specified region of a vector (or linearized array) to be written.
+@deffn {Scheme Procedure} struct-vtable handle
+@deffnx {C Function} scm_struct_vtable (handle)
+Return the vtable structure that describes the type of @var{struct}.
+@end deffn
 
-The number of objects actually written is returned.
-@var{port-or-fdes} may be
-omitted, in which case it defaults to the value returned by
-@code{(current-output-port)}.
+@deffn {Scheme Procedure} struct-vtable? x
+@deffnx {C Function} scm_struct_vtable_p (x)
+Return @code{#t} iff @var{x} is a vtable structure.
 @end deffn
 
-@node Bit Vectors
-@subsubsection Bit Vectors
+If you have a vtable structure, @code{V}, you can create an instance of
+the type it describes by using @code{(make-struct V ...)}.  But where
+does @code{V} itself come from?  One possibility is that @code{V} is an
+instance of a user-defined vtable type, @code{V'}, so that @code{V} is
+created by using @code{(make-struct V' ...)}.  Another possibility is
+that @code{V} is an instance of the type it itself describes.  Vtable
+structures of the second sort are created by this procedure:
 
-@noindent
-Bit vectors are a specific type of uniform array: an array of booleans
-with a single zero-based index.
+@deffn {Scheme Procedure} make-vtable-vtable user_fields tail_array_size . init
+@deffnx {C Function} scm_make_vtable_vtable (user_fields, tail_array_size, init)
+Return a new, self-describing vtable structure.
 
-@noindent
-They are displayed as a sequence of @code{0}s and
-@code{1}s prefixed by @code{#*}, e.g.,
+@var{user-fields} is a string describing user defined fields of the
+vtable beginning at index @code{vtable-offset-user}
+(see @code{make-struct-layout}).
 
-@example
-(make-uniform-vector 8 #t #f) @result{}
-#*00000000
-@end example
+@var{tail-size} specifies the size of the tail-array (if any) of
+this vtable.
 
-@deffn {Scheme Procedure} bit-count bool bitvector
-@deffnx {C Function} scm_bit_count (bool, bitvector)
-Return a count of how many entries in @var{bitvector} are equal to
-@var{bool}.  For example,
+@var{init1}, @dots{} are the optional initializers for the fields of
+the vtable.
 
-@example
-(bit-count #f #*000111000)  @result{} 6
-@end example
-@end deffn
+Vtables have one initializable system field---the struct printer.
+This field comes before the user fields in the initializers passed
+to @code{make-vtable-vtable} and @code{make-struct}, and thus works as
+a third optional argument to @code{make-vtable-vtable} and a fourth to
+@code{make-struct} when creating vtables:
 
-@deffn {Scheme Procedure} bit-position bool bitvector start
-@deffnx {C Function} scm_bit_position (bool, bitvector, start)
-Return the index of the first occurrance of @var{bool} in
-@var{bitvector}, starting from @var{start}.  If there is no @var{bool}
-entry between @var{start} and the end of @var{bitvector}, then return
-@code{#f}.  For example,
+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.
 
-@example
-(bit-position #t #*000101 0)  @result{} 3
-(bit-position #f #*0001111 3) @result{} #f
-@end example
-@end deffn
+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.
 
-@deffn {Scheme Procedure} bit-invert! bitvector
-@deffnx {C Function} scm_bit_invert_x (bitvector)
-Modify @var{bitvector} by replacing each element with its negation.
-@end deffn
+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.)
 
-@deffn {Scheme Procedure} bit-set*! bitvector uvec bool
-@deffnx {C Function} scm_bit_set_star_x (bitvector, uvec, bool)
-Set entries of @var{bitvector} to @var{bool}, with @var{uvec}
-selecting the entries to change.  The return value is unspecified.
+@lisp
+(define ball-root (make-vtable-vtable "pr" 0))
 
-If @var{uvec} is a bit vector, then those entries where it has
-@code{#t} are the ones in @var{bitvector} which are set to @var{bool}.
-@var{uvec} and @var{bitvector} must be the same length.  When
-@var{bool} is @code{#t} it's like @var{uvec} is OR'ed into
-@var{bitvector}.  Or when @var{bool} is @code{#f} it can be seen as an
-ANDNOT.
+(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))
 
-@example
-(define bv #*01000010)
-(bit-set*! bv #*10010001 #t)
-bv
-@result{} #*11010011
-@end example
+(define red (make-ball-type 'red))
+(define green (make-ball-type 'green))
 
-If @var{uvec} is a uniform vector of unsigned long integers, then
-they're indexes into @var{bitvector} which are set to @var{bool}.  
+(define (make-ball type owner) (make-struct type 0 owner))
 
-@example
-(define bv #*01000010)
-(bit-set*! bv #u(5 2 7) #t)
-bv
-@result{} #*01100111
-@end example
+(define ball (make-ball green 'Nisse))
+ball @result{} #<a green ball owned by Nisse>
+@end lisp
 @end deffn
 
-@deffn {Scheme Procedure} bit-count* bitvector uvec bool
-@deffnx {C Function} scm_bit_count_star (bitvector, uvec, bool)
-Return a count of how many entries in @var{bitvector} are equal to
-@var{bool}, with @var{uvec} selecting the entries to consider.
-
-@var{uvec} is interpreted in the same way as for @code{bit-set*!}
-above.  Namely, if @var{uvec} is a bit vector then entries which have
-@code{#t} there are considered in @var{bitvector}.  Or if @var{uvec}
-is a uniform vector of unsigned long integers then it's the indexes in
-@var{bitvector} to consider.
+@deffn {Scheme Procedure} struct-vtable-name vtable
+@deffnx {C Function} scm_struct_vtable_name (vtable)
+Return the name of the vtable @var{vtable}.
+@end deffn
 
-For example,
+@deffn {Scheme Procedure} set-struct-vtable-name! vtable name
+@deffnx {C Function} scm_set_struct_vtable_name_x (vtable, name)
+Set the name of the vtable @var{vtable} to @var{name}.
+@end deffn
 
-@example
-(bit-count* #*01110111 #*11001101 #t) @result{} 3
-(bit-count* #*01110111 #u(7 0 4) #f)  @result{} 2
-@end example
+@deffn {Scheme Procedure} struct-vtable-tag handle
+@deffnx {C Function} scm_struct_vtable_tag (handle)
+Return the vtable tag of the structure @var{handle}.
 @end deffn
 
 
@@ -1793,10 +3049,9 @@ of tools for using either association lists or hash tables.
 @subsection Association Lists
 @tpindex Association Lists
 @tpindex Alist
-
-@cindex Association List
-@cindex Alist
-@cindex Database
+@cindex association List
+@cindex alist
+@cindex aatabase
 
 An association list is a conventional data structure that is often used
 to implement simple key-value databases.  It consists of a list of
@@ -1991,11 +3246,10 @@ association list.
 @rnindex assv
 @rnindex assoc
 
-@code{assq}, @code{assv} and @code{assoc} take an alist and a key as
-arguments and return the entry for that key if an entry exists, or
-@code{#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 @code{(KEY . VALUE)}, not just the value.
+@code{assq}, @code{assv} and @code{assoc} find the entry in an alist
+for a given key, and return the @code{(@var{key} . @var{value})} pair.
+@code{assq-ref}, @code{assv-ref} and @code{assoc-ref} do a similar
+lookup, but return just the @var{value}.
 
 @deffn {Scheme Procedure} assq key alist
 @deffnx {Scheme Procedure} assv key alist
@@ -2003,26 +3257,13 @@ is @code{(KEY . VALUE)}, not just the value.
 @deffnx {C Function} scm_assq (key, alist)
 @deffnx {C Function} scm_assv (key, alist)
 @deffnx {C Function} scm_assoc (key, alist)
-Fetch the entry in @var{alist} that is associated with @var{key}.  To
-decide whether the argument @var{key} matches a particular entry in
-@var{alist}, @code{assq} compares keys with @code{eq?}, @code{assv}
-uses @code{eqv?} and @code{assoc} uses @code{equal?}.  If @var{key}
-cannot be found in @var{alist} (according to whichever equality
-predicate is in use), then return @code{#f}.  These functions
-return the entire alist entry found (i.e. both the key and the value).
-@end deffn
-
-@code{assq-ref}, @code{assv-ref} and @code{assoc-ref}, on the other
-hand, take an alist and a key and return @emph{just the value} for that
-key, if an entry exists.  If there is no entry for the specified key,
-these procedures return @code{#f}.
-
-This creates an ambiguity: if the return value is @code{#f}, it means
-either that there is no entry with the specified key, or that there
-@emph{is} an entry for the specified key, with value @code{#f}.
-Consequently, @code{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.
+Return the first entry in @var{alist} with the given @var{key}.  The
+return is the pair @code{(KEY . VALUE)} from @var{alist}.  If there's
+no matching entry the return is @code{#f}.
+
+@code{assq} compares keys with @code{eq?}, @code{assv} uses
+@code{eqv?} and @code{assoc} uses @code{equal?}.
+@end deffn
 
 @deffn {Scheme Procedure} assq-ref alist key
 @deffnx {Scheme Procedure} assv-ref alist key
@@ -2030,18 +3271,22 @@ for some other reason.
 @deffnx {C Function} scm_assq_ref (alist, key)
 @deffnx {C Function} scm_assv_ref (alist, key)
 @deffnx {C Function} scm_assoc_ref (alist, key)
-Like @code{assq}, @code{assv} and @code{assoc}, except that only the
-value associated with @var{key} in @var{alist} is returned.  These
-functions are equivalent to
+Return the value from the first entry in @var{alist} with the given
+@var{key}, or @code{#f} if there's no such entry.
 
-@lisp
-(let ((ent (@var{associator} @var{key} @var{alist})))
-  (and ent (cdr ent)))
-@end lisp
+@code{assq-ref} compares keys with @code{eq?}, @code{assv-ref} uses
+@code{eqv?} and @code{assoc-ref} uses @code{equal?}.
 
-where @var{associator} is one of @code{assq}, @code{assv} or @code{assoc}.
+Notice these functions have the @var{key} argument last, like other
+@code{-ref} functions, but this is opposite to what what @code{assq}
+etc above use.
+
+When the return is @code{#f} it can be either @var{key} not found, or
+an entry which happens to have value @code{#f} in the @code{cdr}.  Use
+@code{assq} etc above if you need to differentiate these cases.
 @end deffn
 
+
 @node Removing Alist Entries
 @subsubsection Removing Alist Entries
 
@@ -2216,8 +3461,6 @@ capitals
 @subsection Hash Tables
 @tpindex Hash Tables
 
-@c FIXME::martin: Review me!
-
 Hash tables are dictionaries which offer similar functionality as
 association lists: They provide a mapping from keys to values.  The
 difference is that association lists need time linear in the size of
@@ -2226,6 +3469,12 @@ search in constant time.  The drawback is that hash tables require a
 little bit more memory, and that you can not use the normal list
 procedures (@pxref{Lists}) for working with them.
 
+Guile provides two types of hashtables.  One is an abstract data type
+that can only be manipulated with the functions in this section.  The
+other type is concrete: it uses a normal vector with alists as
+elements.  The advantage of the abstract hash tables is that they will
+be automatically resized when they become too full or too empty.
+
 @menu
 * Hash Table Examples::         Demonstration of hash table usage.
 * Hash Table Reference::        Hash table procedure descriptions.
@@ -2235,8 +3484,6 @@ procedures (@pxref{Lists}) for working with them.
 @node Hash Table Examples
 @subsubsection Hash Table Examples
 
-@c FIXME::martin: Review me!
-
 For demonstration purposes, this section gives a few usage examples of
 some hash table procedures, together with some explanation what they do.
 
@@ -2246,17 +3493,42 @@ populate it with two key/value pairs.
 @lisp
 (define h (make-hash-table 31))
 
-(hashq-create-handle! h 'foo "bar")
+;; This is an opaque object
+h
 @result{}
-(foo . "bar")
+#<hash-table 0/31>
+
+;; We can also use a vector of alists.
+(define h (make-vector 7 '()))
+
+h
+@result{}
+#(() () () () () () ())
+
+;; Inserting into a hash table can be done with hashq-set!
+(hashq-set! h 'foo "bar")
+@result{}
+"bar"
 
-(hashq-create-handle! h 'braz "zonk")
+(hashq-set! h 'braz "zonk")
 @result{}
-(braz . "zonk")
+"zonk"
 
+;; Or with hash-create-handle!
 (hashq-create-handle! h 'frob #f)
 @result{}
 (frob . #f)
+
+;; The vector now contains three elements in the alists and the frob
+;; entry is at index (hashq 'frob).
+h
+@result{}
+#(() () () () ((frob . #f) (braz . "zonk")) () ((foo . "bar")))
+
+(hashq 'frob)
+@result{}
+4
+
 @end lisp
 
 You can get the value for a given key with the procedure
@@ -2321,18 +3593,24 @@ A single @code{make-hash-table} creates a hash table suitable for use
 with any set of functions, but it's imperative that just one set is
 then used consistently, or results will be unpredictable.
 
-@sp 1
 Hash tables are implemented as a vector indexed by a hash value formed
 from the key, with an association list of key/value pairs for each
 bucket in case distinct keys hash together.  Direct access to the
 pairs in those lists is provided by the @code{-handle-} functions.
+The abstract kind of hash tables hide the vector in an opaque object
+that represents the hash table, while for the concrete kind the vector
+@emph{is} the hashtable.
 
-When the number of table entries goes above a threshold the vector is
-increased and the entries rehashed, to prevent the bucket lists
-becoming too long and slowing down accesses.  When the number of
-entries goes below a threshold the vector is decreased to save space.
+When the number of table entries in an abstract hash table goes above
+a threshold, the vector is made larger and the entries are rehashed,
+to prevent the bucket lists from becoming too long and slowing down
+accesses.  When the number of entries goes below a threshold, the
+vector is shrunk to save space.
+
+A abstract hash table is created with @code{make-hash-table}.  To
+create a vector that is suitable as a hash table, use
+@code{(make-vector @var{size} '())}, for example.
 
-@sp 1
 For the @code{hashx-} ``extended'' routines, an application supplies a
 @var{hash} function producing an integer index like @code{hashq} etc
 below, and an @var{assoc} alist search function like @code{assq} etc
@@ -2361,16 +3639,13 @@ values are arbitrary as long as they're in the range 0 to
 @math{@var{size}-1}.  Helpful functions for forming a hash value, in
 addition to @code{hashq} etc below, include @code{symbol-hash}
 (@pxref{Symbol Keys}), @code{string-hash} and @code{string-hash-ci}
-(@pxref{SRFI-13 Comparison}), and @code{char-set-hash} (@pxref{SRFI-14
-Predicates/Comparison}).
-
-Note that currently, unfortunately, there's no @code{hashx-remove!}
-function, which rather limits the usefulness of the @code{hashx-}
-routines.
+(@pxref{String Comparison}), and @code{char-set-hash}
+(@pxref{Character Set Predicates/Comparison}).
 
 @sp 1
 @deffn {Scheme Procedure} make-hash-table [size]
-Create a new hash table, with an optional minimum vector @var{size}.
+Create a new abstract hash table object, with an optional minimum
+vector @var{size}.
 
 When @var{size} is given, the table vector will still grow and shrink
 automatically, as described above, but with @var{size} as a minimum.
@@ -2379,6 +3654,16 @@ then it can use @var{size} to avoid rehashing when initial entries are
 added.
 @end deffn
 
+@deffn {Scheme Procedure} hash-table? obj
+@deffnx {C Function} scm_hash_table_p (obj)
+Return @code{#t} if @var{obj} is a abstract hash table object.
+@end deffn
+
+@deffn {Scheme Procedure} hash-clear! table
+@deffnx {C Function} scm_hash_clear_x (table)
+Remove all items from @var{table} (without triggering a resize).
+@end deffn
+
 @deffn {Scheme Procedure} hash-ref table key [dflt]
 @deffnx {Scheme Procedure} hashq-ref table key [dflt]
 @deffnx {Scheme Procedure} hashv-ref table key [dflt]
@@ -2408,9 +3693,11 @@ If it's not present then a new entry is created.
 @deffn {Scheme Procedure} hash-remove! table key
 @deffnx {Scheme Procedure} hashq-remove! table key
 @deffnx {Scheme Procedure} hashv-remove! table key
+@deffnx {Scheme Procedure} hashx-remove! hash assoc table key
 @deffnx {C Function} scm_hash_remove_x (table, key)
 @deffnx {C Function} scm_hashq_remove_x (table, key)
 @deffnx {C Function} scm_hashv_remove_x (table, key)
+@deffnx {C Function} scm_hashx_remove_x (hash, assoc, table, key)
 Remove any association for @var{key} in the given hash @var{table}.
 If @var{key} is not in @var{table} then nothing is done.
 @end deffn