Renamed the "frames" that are related to dynamic-wind to "dynamic
[bpt/guile.git] / doc / ref / api-compound.texi
index 733e780..a47b2d2 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
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -63,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)
@@ -104,9 +104,9 @@ 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
@@ -117,6 +117,16 @@ are also predefined.
 Return the car or the cdr of @var{pair}, respectively.
 @end deffn
 
+@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
@@ -263,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
@@ -542,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
@@ -635,19 +648,15 @@ 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 vectors are the special case of non-uniform, one-dimensional
-arrays and that most array procedures operate happily on vectors
+that vectors are the special case of one dimensional non-uniform arrays
+and that most array procedures operate happily on vectors
 (@pxref{Arrays}).
 
-C code must deal with the additional distinction between @dfn{simple}
-and non-@dfn{simple} vector.  A simple vector is one whose elements
-are stored in contiguous memory locations.  Most vectors are simple,
-but some vectors produced by @code{make-shared-array} are not.
-
 @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
 
 
@@ -668,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)
@@ -696,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
@@ -781,7 +784,7 @@ Return the contents of position @var{k} of @var{vector}.
 @end deffn
 
 @deftypefn {C Function} SCM scm_c_vector_ref (SCM v, size_t k)
-Return the contents of position @var{k} (s @code{size_t}) of
+Return the contents of position @var{k} (a @code{size_t}) of
 @var{vector}.
 @end deftypefn
 
@@ -818,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},
@@ -842,62 +850,119 @@ same vector, @code{vector-move-right!} is usually appropriate when
 @var{start1} is less than @var{start2}.
 @end deffn
 
-@deftypefn {C Function} {const SCM *} scm_vector_elements (SCM vec)
-Return a pointer to the memory that holds the elements of @var{vec}
-for reading.  The vector @var{vec} must be simple.
+@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
 
-For each call to this function, you must call
-@code{scm_vector_release_elements} and after that call the pointer to
-the elements becomes invalid.
+@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 Function} void scm_vector_release_elements (SCM vec)
-Finish the access to the elements of a simple vector, as exlained above.
+@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 Function} void scm_frame_vector_release_elements (SCM vec)
-Arrange for @code{scm_vector_release_elements} to be called with @var{vec}
-when the current frame is unwound, implicitely or explicitely;
-@xref{Frames}.
+@deftypefn {C Macro} void SCM_SIMPLE_VECTOR_SET_X (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} SCM *scm_vector_writable_elements (SCM vec)
-Return a pointer to the memory that holds the elements of @var{vec}
-for writing.  The vector @var{vec} must be simple.
+@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}.
 
-For each call to this function, you must call
-@code{scm_vector_release_writable_elements} and after that call the
-pointer to the elements becomes invalid.
-@end deftypefn
+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).
+
+@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
 
-@deftypefn {C Function} void scm_vector_release_writable_elements (SCM vec)
-Finish the access to the elements of a vector, as exlained above.
 @end deftypefn
 
-@deftypefn {C Function} void scm_frame_vector_release_writable_elements (SCM vec)
-Arrange for @code{scm_vector_release_writable_elements} to be called
-with @var{vec} when the current frame is unwound, implicitely or
-explicitely; @xref{Frames}.
+@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.
+
+The following example shows the typical way to use this function.  It
+fills a vector with @code{#t}.
+
+@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
+
 @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 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.
+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 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,
+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, zero-origin 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
@@ -919,17 +984,21 @@ 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.
-
-One set of these procedures is a generic one: it works with all types of
-uniform 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-vector} in its names,
-the specific ones use the tag from the following table.
+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
@@ -1000,19 +1069,19 @@ anyway to make the intention clear, so this is rarely a problem.
 @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
+@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
@@ -1059,18 +1128,18 @@ unspecified.
 @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
+@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.
@@ -1089,19 +1158,19 @@ the number of parameters given.
 @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
+@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
 
@@ -1118,19 +1187,19 @@ Return the number of elements in @var{vec}.
 @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
+@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
@@ -1148,19 +1217,19 @@ in @var{vec} is index 0.
 @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
+@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.
@@ -1179,19 +1248,19 @@ unspecified.
 @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
+@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
 
@@ -1207,18 +1276,18 @@ Return a newly allocated list holding all elements of @var{vec}.
 @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
+@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
@@ -1235,25 +1304,27 @@ initialized with the elements of the list @var{lst}.
 @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 newly allocated homogeneous numeric vector of the indicated
+@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.
+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 @code{1} when @var{uvec} is a uniform vector, @code{0} otherwise.
+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)
@@ -1268,10 +1339,11 @@ Return @code{1} when @var{uvec} is a uniform vector, @code{0} otherwise.
 @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 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.
+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
@@ -1279,89 +1351,95 @@ are at even indices in that array, the corresponding imaginary parts are
 at the following odd index.
 @end deftypefn
 
-@deftypefn  {C Function} {const void *} scm_uniform_vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_uint8 *} scm_u8vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_int8 *} scm_s8vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_uint16 *} scm_u16vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_int16 *} scm_s16vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_uint32 *} scm_u32vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_int32 *} scm_s32vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_uint64 *} scm_u64vector_elements (SCM uvec)
-@deftypefnx {C Function} {const scm_t_int64 *} scm_s64vector_elements (SCM uvec)
-@deftypefnx {C Function} {const float *} scm_f32vector_elements (SCM uvec)
-@deftypefnx {C Function} {const double *} scm_f64vector_elements (SCM uvec)
-@deftypefnx {C Function} {const float *} scm_c32vector_elements (SCM uvec)
-@deftypefnx {C Function} {const double *} scm_c64vector_elements (SCM uvec)
-Return a pointer to the elements of a uniform vector for reading.  For
-each call to one of these functions, you must call
-@code{scm_uniform_vector_release_elements} and after that call the pointer to
-the elements becomes invalid.
-
-The @code{c32} and @code{c64} variants return pointers 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.
+@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} void scm_uniform_vector_release_elements (SCM uvec)
-Finish the access to the elements of a uniform vector, as exlained
-above.
+@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_frame_uniform_vector_release_elements (SCM uvec)
-Arrange for @code{scm_uniform_vector_release_elements} to be called with
-@var{uvec} when the current frame is unwound, implicitely or
-explicitely; @xref{Frames}.
+@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
 
-@deftypefn  {C Function} {void *} scm_uniform_vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_uint8 *} scm_u8vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_int8 *} scm_s8vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_uint16 *} scm_u16vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_int16 *} scm_s16vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_uint32 *} scm_u32vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_int32 *} scm_s32vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_uint64 *} scm_u64vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {scm_t_int64 *} scm_s64vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {float *} scm_f32vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {double *} scm_f64vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {float *} scm_c32vector_writable_elements (SCM uvec)
-@deftypefnx {C Function} {double *} scm_c64vector_writable_elements (SCM uvec)
-Return a pointer to the elements of a uniform vector for writing.  For
-each call to one of these functions, you must call
-@code{scm_uniform_vector_release_writable_elements} and after that
-call the pointer to the elements becomes invalid.
-
-The @code{c32} and @code{c64} variants return pointers 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
+@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.
 
-@deftypefn {C Function} void scm_uniform_vector_release_writable_elements (SCM uvec)
-Finish the access to the elements of a uniform vector, as exlained
-above.
-@end deftypefn
+The optional arguments @var{start} (inclusive) and @var{end}
+(exclusive) allow a specified region to be read,
+leaving the remainder of the vector unchanged.
 
-@deftypefn {C Function} void scm_frame_uniform_vector_release_writable_elements (SCM uvec)
-Arrange for @code{scm_uniform_vector_release_writable_elements} to be called with
-@var{uvec} when the current frame is unwound, implicitely or
-explicitely; @xref{Frames}.
-@end deftypefn
+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.
 
-@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
+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).
 
-@deftypefn {C Function} size_t scm_c_uniform_vector_element_size (SCM uvec)
-Return the number of bytes of one element of @var{uvec}.
-@end deftypefn
+@code{uniform-vector-read!} returns the number of elements
+read.
 
-@deftypefn {C Function} size_t scm_c_uniform_vector_size (SCM uvec)
-Return the number of bytes used by all elements of @var{uvec}.  This is
-just @code{scm_c_uniform_vector_length (@var{uvec}) *
-scm_c_uniform_vector_element_size (@var{uvec})}.
-@end deftypefn
+@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-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.
+
+The optional arguments @var{start} (inclusive)
+and @var{end} (exclusive) allow
+a specified region to be written.
+
+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.
+
+An error is signalled when the last element has only
+been partially written in the single call to write(2).
+
+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 Bit Vectors
@@ -1379,6 +1457,7 @@ are displayed as a sequence of @code{0}s and @code{1}s prefixed by
 
 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.
 
 @deffn {Scheme Procedure} bitvector? obj
 @deffnx {C Function} scm_bitvector_p (obj)
@@ -1456,56 +1535,6 @@ Return a new list initialized with the elements
 of the bitvector @var{vec}.
 @end deffn
 
-@deftypefn {C Function} {const scm_t_uint32 *} scm_bitvector_elements (SCM vec)
-Return a pointer to the memory that holds the elements of @var{vec}
-for reading.  Each word pointed to by this pointer has exactly 32
-bits, the least significant bit having the lowest index.
-
-There are @code{(scm_c_bitvector_length(@var{vec})+31)/32} words in the
-returned memory block.  The last word might be only partially used when
-the bitvector length is not a multiple of 32.  The unused bits must be
-ignored during reading.
-
-For each call to this function, you must call
-@code{scm_bitvector_release_elements} and after that call the pointer
-to the elements becomes invalid.
-@end deftypefn
-
-@deftypefn {C Function} void scm_bitvector_release_elements (SCM vec)
-Finish the access to the elements of a bitvector, as exlained above.
-@end deftypefn
-
-@deftypefn {C Function} void scm_frame_bitvector_release_elements (SCM vec)
-Arrange for @code{scm_bitvector_release_elements} to be called with @var{vec}
-when the current frame is unwound, implicitely or explicitely;
-@xref{Frames}.
-@end deftypefn
-
-@deftypefn {C Function} scm_t_uint32 *scm_bitvector_writable_elements (SCM vec)
-Return a pointer to the memory that holds the elements of @var{vec}
-for writing.  Each word pointed to by this pointer has exactly 32
-bits, the least significant bit having the lowest index.
-
-There are @code{(scm_c_bitvector_length(@var{vec})+31)/32} words in
-the returned memory block.  The last word might be only partially used
-when the bitvector length is not a multiple of 32.  The unused bits
-can be overwritten freely since they must be ignored during reading.
-
-For each call to this function, you must call
-@code{scm_bitvector_release_writable_elements} and after that call the
-pointer to the elements becomes invalid.
-@end deftypefn
-
-@deftypefn {C Function} void scm_bitvector_release_writable_elements (SCM vec)
-Finish the access to the elements of a bitvector, as exlained above.
-@end deftypefn
-
-@deftypefn {C Function} void scm_frame_bitvector_release_writable_elements (SCM vec)
-Arrange for @code{scm_bitvector_release_writable_elements} to be
-called with @var{vec} when the current frame is unwound, implicitely
-or explicitely; @xref{Frames}.
-@end deftypefn
-
 @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
@@ -1583,6 +1612,18 @@ For example,
 @end example
 @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 Generalized Vectors
 @subsection Generalized Vectors
@@ -1597,9 +1638,6 @@ 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.
 
-Generalized vectors play an important role as the underlying storage
-for arrays, @xref{Arrays}.
-
 @deffn {Scheme Procedure} generalized-vector? obj
 @deffnx {C Function} scm_generalized_vector_p (obj)
 Return @code{#t} if @var{obj} is a vector, string,
@@ -1647,6 +1685,14 @@ Set the element at index @var{idx} of the generalized vector @var{v}
 to @var{val}.
 @end deftypefn
 
+@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
+
 @node Arrays
 @subsection Arrays
 @tpindex Arrays
@@ -1668,23 +1714,44 @@ 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 a inclusive lower and upper bound.  These bounds can
-well be negative, but the upper bound must be grater than or equal to
-the lower bound.  When all lower bounds of an array are zero, it is
-called a @dfn{zero-origin} array.
+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.
 
-For example, ordinary vectors can be regarded as one-dimensional,
-zero-origin arrays.
+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.
+
+@menu
+* Array Syntax::                
+* Array Procedures::            
+* Shared Arrays::               
+* Accessing Arrays from C::     
+@end menu
+
+@node Array Syntax
+@subsubsection Array Syntax
 
 An array is displayed as @code{#} followed by its rank, followed by a
-tag that describes the underlying vector, optionally followed by the
-lower bounds, and finally followed by the cells, organized into
-dimensions using parentheses.
+tag that describes the underlying vector, optionally followed by
+information about its shape, and finally followed by the cells,
+organized into dimensions using parentheses.
 
 In more words, the array tag is of the form
 
 @example
-  #<rank><vectag><@@lower><@@lower>...
+  #<rank><vectag><@@lower><:len><@@lower><:len>...
 @end example
 
 where @code{<rank>} is a positive integer in decimal giving the rank of
@@ -1697,11 +1764,23 @@ 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.
 
-The @code{<@@lower>} part is a @samp{@@} sign followed by an integer in
-decimal giving the lower bound of a dimension.  There is one
+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.
 
+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.
+
+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.
+
 Thus, 
 
 @table @code
@@ -1722,8 +1801,21 @@ is a uniform u8 array of rank 1.
 @item #2u32@@2@@3((1 2) (2 3))
 is a uniform u8 array of rank 2 with index ranges 2..3 and 3..4.
 
+@item #2()
+is a two-dimensional array with index ranges 0..-1 and 0..-1, i.e. both
+dimensions have length zero.
+
+@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.
+
+@item #0(12)
+is a rank-zero array with contents 12.
+
 @end table
 
+@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:
@@ -1788,9 +1880,12 @@ 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.
 
-Ordinary arrays (signified by a @var{type} of @code{#t}) are filled
-with @var{fill}.  Other types of arrays are only then filled with
-@var{fill} when @var{fill} is non-@nicode{#f}.
+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
@@ -1841,7 +1936,7 @@ 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
@@ -1858,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
-affine, 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
@@ -1965,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
@@ -2002,20 +2042,6 @@ same type, and have corresponding elements which are either
 @var{array-equal?} but not @var{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-generalized-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
-
 @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?
@@ -2119,6 +2145,443 @@ 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) (* 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
 
@@ -2581,10 +3044,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
@@ -2779,11 +3241,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
@@ -2791,26 +3252,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
@@ -2818,18 +3266,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?}.
+
+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.
 
-where @var{associator} is one of @code{assq}, @code{assv} or @code{assoc}.
+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
 
@@ -3004,8 +3456,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
@@ -3014,6 +3464,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.
@@ -3023,8 +3479,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.
 
@@ -3034,17 +3488,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{}
+#(() () () () () () ())
 
-(hashq-create-handle! h 'braz "zonk")
+;; Inserting into a hash table can be done with hashq-set!
+(hashq-set! h 'foo "bar")
 @result{}
-(braz . "zonk")
+"bar"
 
+(hashq-set! h 'braz "zonk")
+@result{}
+"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
@@ -3109,18 +3588,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
@@ -3152,13 +3637,10 @@ addition to @code{hashq} etc below, include @code{symbol-hash}
 (@pxref{String Comparison}), and @code{char-set-hash}
 (@pxref{Character Set Predicates/Comparison}).
 
-Note that currently, unfortunately, there's no @code{hashx-remove!}
-function, which rather limits the usefulness of the @code{hashx-}
-routines.
-
 @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.
@@ -3169,12 +3651,12 @@ added.
 
 @deffn {Scheme Procedure} hash-table? obj
 @deffnx {C Function} scm_hash_table_p (obj)
-Return @code{#t} if @var{obj} is a hash table.
+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 TABLE (without triggering a resize).
+Remove all items from @var{table} (without triggering a resize).
 @end deffn
 
 @deffn {Scheme Procedure} hash-ref table key [dflt]
@@ -3206,9 +3688,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