Changes from arch/CVS synchronization
[bpt/guile.git] / doc / ref / api-compound.texi
index 7f94359..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.
 
@@ -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
@@ -808,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},
@@ -843,7 +861,9 @@ 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).
+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
@@ -865,22 +885,27 @@ 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_X (SCM vec, size_t idx, SCM val)
+@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)
+@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.
+@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 between elements,
-respectively.  Note that the increment can well be negative.
+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 @code{vec} (in reverse order).
+creates a list of all elements of @var{vec} (in reverse order).
 
 @example
 scm_t_array_handle handle;
@@ -893,11 +918,12 @@ 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
 
 @end deftypefn
 
-@deftypefn {C Function} SCM *scm_vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
+@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.
 
@@ -910,9 +936,10 @@ size_t i, len;
 ssize_t inc;
 SCM *elt;
 
-elt = scm_vector_elements (vec, &handle, &len, &inc);
+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
@@ -1042,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
@@ -1101,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.
@@ -1131,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
 
@@ -1160,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
@@ -1190,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.
@@ -1221,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
 
@@ -1249,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
@@ -1277,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)
@@ -1310,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
@@ -1325,16 +1355,92 @@ at the following odd index.
 Return the number of elements of @var{uvec} as a @code{size_t}.
 @end deftypefn
 
-@deftypefn {C Function} size_t scm_c_uniform_vector_element_size (SCM uvec)
-Return the number of bytes of one element of @var{uvec}.
+@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} 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})}.
+@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.
+
+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).
+
+@code{uniform-vector-read!} returns the number of elements
+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-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
 @subsection Bit Vectors
@@ -1506,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
@@ -1567,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
@@ -1583,37 +1709,49 @@ 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.
-When all lower bounds of an array are zero, it is called a
-@dfn{zero-origin} array.
-
-For example, ordinary vectors are the special case of one dimensional,
-ordinary arrays and strings are one dimensional character arrays.
+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.
 
 @menu
-* Array Syntax::
-* Array Procedures::
-* Accessing Arrays from C::    
+* 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
@@ -1626,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
@@ -1651,6 +1801,17 @@ 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
@@ -1775,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
@@ -1792,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
@@ -1899,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
@@ -1932,22 +2038,9 @@ 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.
-@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.
+@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
 
 @c  FIXME: array-map! accepts no source arrays at all, and in that
@@ -2053,6 +2146,166 @@ 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
 
@@ -2060,41 +2313,275 @@ 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 code such as linear algebra libraries or image processing
+external 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 it
-can not be modified.  When you try to modify it, an error is signalled.
+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 frame (@pxref{Frames}): a call to
-@code{scm_array_get_handle} can be thought of as beginning a frame and
-@code{scm_array_handle_release} as ending it.  When a non-local exit
-happens between these two calls, the array is implicitely unreserved.
+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 dynamic contexts
-need to be properly nested.  If you begin a frame prior to reserving an
-array, you need to unreserve the array before ending the frame.
-Likewise, when reserving two or more arrays in a certain order, you need
-to unreserve them in the opposite order.
+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.  Arrays that
-result from such an operation are not stored contiguously in memory and
-when working with them, you need to take this into account.
+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
@@ -2218,6 +2705,10 @@ 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{}
@@ -2558,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
@@ -2756,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
@@ -2768,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
@@ -2795,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
 
@@ -2981,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
@@ -2991,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.
@@ -3000,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.
 
@@ -3011,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>
 
-(hashq-create-handle! h 'braz "zonk")
+;; 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-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
@@ -3086,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
@@ -3129,13 +3642,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.
@@ -3146,12 +3656,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]
@@ -3183,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