X-Git-Url: https://git.hcoop.net/bpt/guile.git/blobdiff_plain/7cf2d3d520700685260ee9107cc3bfe8c8cfb093..661ae7ab6be5aec4d6107902cff94dbb8952a24a:/doc/ref/api-compound.texi diff --git a/doc/ref/api-compound.texi b/doc/ref/api-compound.texi index 733e780f5..a47b2d28e 100644 --- a/doc/ref/api-compound.texi +++ b/doc/ref/api-compound.texi @@ -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__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 - #<@@lower><@@lower>... + #<@@lower><:len><@@lower><:len>... @end example where @code{} is a positive integer in decimal giving the rank of @@ -1697,11 +1764,23 @@ The @code{} 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()}, where @code{} 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__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__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") +# + +;; 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