mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
3818 lines
146 KiB
Text
3818 lines
146 KiB
Text
@c -*-texinfo-*-
|
||
@c This is part of the GNU Guile Reference Manual.
|
||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004
|
||
@c Free Software Foundation, Inc.
|
||
@c See the file guile.texi for copying conditions.
|
||
|
||
@page
|
||
@node Compound Data Types
|
||
@section Compound Data Types
|
||
|
||
This chapter describes Guile's compound data types. By @dfn{compound}
|
||
we mean that the primary purpose of these data types is to act as
|
||
containers for other kinds of data (including other compound objects).
|
||
For instance, a (non-uniform) vector with length 5 is a container that
|
||
can hold five arbitrary Scheme objects.
|
||
|
||
The various kinds of container object differ from each other in how
|
||
their memory is allocated, how they are indexed, and how particular
|
||
values can be looked up within them.
|
||
|
||
@menu
|
||
* Pairs:: Scheme's basic building block.
|
||
* Lists:: Special list functions supported by Guile.
|
||
* Vectors:: One-dimensional arrays of Scheme objects.
|
||
* Uniform Numeric Vectors:: Vectors with elements of a single numeric type.
|
||
* Bit Vectors:: Vectors of bits.
|
||
* Generalized Vectors:: Treating all vector-like things uniformly.
|
||
* Arrays:: Matrices, etc.
|
||
* Records::
|
||
* Structures::
|
||
* Dictionary Types:: About dictionary types in general.
|
||
* Association Lists:: List-based dictionaries.
|
||
* Hash Tables:: Table-based dictionaries.
|
||
@end menu
|
||
|
||
|
||
@node Pairs
|
||
@subsection Pairs
|
||
@tpindex Pairs
|
||
|
||
Pairs are used to combine two Scheme objects into one compound object.
|
||
Hence the name: A pair stores a pair of objects.
|
||
|
||
The data type @dfn{pair} is extremely important in Scheme, just like in
|
||
any other Lisp dialect. The reason is that pairs are not only used to
|
||
make two values available as one object, but that pairs are used for
|
||
constructing lists of values. Because lists are so important in Scheme,
|
||
they are described in a section of their own (@pxref{Lists}).
|
||
|
||
Pairs can literally get entered in source code or at the REPL, in the
|
||
so-called @dfn{dotted list} syntax. This syntax consists of an opening
|
||
parentheses, the first element of the pair, a dot, the second element
|
||
and a closing parentheses. The following example shows how a pair
|
||
consisting of the two numbers 1 and 2, and a pair containing the symbols
|
||
@code{foo} and @code{bar} can be entered. It is very important to write
|
||
the whitespace before and after the dot, because otherwise the Scheme
|
||
parser would not be able to figure out where to split the tokens.
|
||
|
||
@lisp
|
||
(1 . 2)
|
||
(foo . bar)
|
||
@end lisp
|
||
|
||
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.
|
||
|
||
@lisp
|
||
'(1 . 2)
|
||
@result{}
|
||
(1 . 2)
|
||
'(foo . bar)
|
||
@result{}
|
||
(foo . bar)
|
||
@end lisp
|
||
|
||
A new pair is made by calling the procedure @code{cons} with two
|
||
arguments. Then the argument values are stored into a newly allocated
|
||
pair, and the pair is returned. The name @code{cons} stands for
|
||
"construct". Use the procedure @code{pair?} to test whether a
|
||
given Scheme object is a pair or not.
|
||
|
||
@rnindex cons
|
||
@deffn {Scheme Procedure} cons x y
|
||
@deffnx {C Function} scm_cons (x, y)
|
||
Return a newly allocated pair whose car is @var{x} and whose
|
||
cdr is @var{y}. The pair is guaranteed to be different (in the
|
||
sense of @code{eq?}) from every previously existing object.
|
||
@end deffn
|
||
|
||
@rnindex pair?
|
||
@deffn {Scheme Procedure} pair? x
|
||
@deffnx {C Function} scm_pair_p (x)
|
||
Return @code{#t} if @var{x} is a pair; otherwise return
|
||
@code{#f}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_pair (SCM x)
|
||
Return 1 when @var{x} is a pair; otherwise return 0.
|
||
@end deftypefn
|
||
|
||
The two parts of a pair are traditionally called @dfn{car} and
|
||
@dfn{cdr}. They can be retrieved with procedures of the same name
|
||
(@code{car} and @code{cdr}), and can be modified with the procedures
|
||
@code{set-car!} and @code{set-cdr!}. Since a very common operation in
|
||
Scheme programs is to access the car of a car of a pair, or the car of
|
||
the cdr of a pair, etc., the procedures called @code{caar},
|
||
@code{cadr} and so on are also predefined.
|
||
|
||
@rnindex car
|
||
@rnindex cdr
|
||
@deffn {Scheme Procedure} car pair
|
||
@deffnx {Scheme Procedure} cdr pair
|
||
@deffnx {C Function} scm_car (pair)
|
||
@deffnx {C Function} scm_cdr (pair)
|
||
Return the car or the cdr of @var{pair}, respectively.
|
||
@end deffn
|
||
|
||
@deftypefn {C Macro} SCM SCM_CAR (SCM pair)
|
||
@deftypefnx {C Macro} SCM SCM_CDR (SCM pair)
|
||
These two macros are the fastest way to access the car or cdr of a
|
||
pair; they can be thought of as compiling into a single memory
|
||
reference.
|
||
|
||
These macros do no checking at all. The argument @var{pair} must be a
|
||
valid pair.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} cddr pair
|
||
@deffnx {Scheme Procedure} cdar pair
|
||
@deffnx {Scheme Procedure} cadr pair
|
||
@deffnx {Scheme Procedure} caar pair
|
||
@deffnx {Scheme Procedure} cdddr pair
|
||
@deffnx {Scheme Procedure} cddar pair
|
||
@deffnx {Scheme Procedure} cdadr pair
|
||
@deffnx {Scheme Procedure} cdaar pair
|
||
@deffnx {Scheme Procedure} caddr pair
|
||
@deffnx {Scheme Procedure} cadar pair
|
||
@deffnx {Scheme Procedure} caadr pair
|
||
@deffnx {Scheme Procedure} caaar pair
|
||
@deffnx {Scheme Procedure} cddddr pair
|
||
@deffnx {Scheme Procedure} cdddar pair
|
||
@deffnx {Scheme Procedure} cddadr pair
|
||
@deffnx {Scheme Procedure} cddaar pair
|
||
@deffnx {Scheme Procedure} cdaddr pair
|
||
@deffnx {Scheme Procedure} cdadar pair
|
||
@deffnx {Scheme Procedure} cdaadr pair
|
||
@deffnx {Scheme Procedure} cdaaar pair
|
||
@deffnx {Scheme Procedure} cadddr pair
|
||
@deffnx {Scheme Procedure} caddar pair
|
||
@deffnx {Scheme Procedure} cadadr pair
|
||
@deffnx {Scheme Procedure} cadaar pair
|
||
@deffnx {Scheme Procedure} caaddr pair
|
||
@deffnx {Scheme Procedure} caadar pair
|
||
@deffnx {Scheme Procedure} caaadr pair
|
||
@deffnx {Scheme Procedure} caaaar pair
|
||
@deffnx {C Function} scm_cddr (pair)
|
||
@deffnx {C Function} scm_cdar (pair)
|
||
@deffnx {C Function} scm_cadr (pair)
|
||
@deffnx {C Function} scm_caar (pair)
|
||
@deffnx {C Function} scm_cdddr (pair)
|
||
@deffnx {C Function} scm_cddar (pair)
|
||
@deffnx {C Function} scm_cdadr (pair)
|
||
@deffnx {C Function} scm_cdaar (pair)
|
||
@deffnx {C Function} scm_caddr (pair)
|
||
@deffnx {C Function} scm_cadar (pair)
|
||
@deffnx {C Function} scm_caadr (pair)
|
||
@deffnx {C Function} scm_caaar (pair)
|
||
@deffnx {C Function} scm_cddddr (pair)
|
||
@deffnx {C Function} scm_cdddar (pair)
|
||
@deffnx {C Function} scm_cddadr (pair)
|
||
@deffnx {C Function} scm_cddaar (pair)
|
||
@deffnx {C Function} scm_cdaddr (pair)
|
||
@deffnx {C Function} scm_cdadar (pair)
|
||
@deffnx {C Function} scm_cdaadr (pair)
|
||
@deffnx {C Function} scm_cdaaar (pair)
|
||
@deffnx {C Function} scm_cadddr (pair)
|
||
@deffnx {C Function} scm_caddar (pair)
|
||
@deffnx {C Function} scm_cadadr (pair)
|
||
@deffnx {C Function} scm_cadaar (pair)
|
||
@deffnx {C Function} scm_caaddr (pair)
|
||
@deffnx {C Function} scm_caadar (pair)
|
||
@deffnx {C Function} scm_caaadr (pair)
|
||
@deffnx {C Function} scm_caaaar (pair)
|
||
These procedures are compositions of @code{car} and @code{cdr}, where
|
||
for example @code{caddr} could be defined by
|
||
|
||
@lisp
|
||
(define caddr (lambda (x) (car (cdr (cdr x)))))
|
||
@end lisp
|
||
@end deffn
|
||
|
||
@rnindex set-car!
|
||
@deffn {Scheme Procedure} set-car! pair value
|
||
@deffnx {C Function} scm_set_car_x (pair, value)
|
||
Stores @var{value} in the car field of @var{pair}. The value returned
|
||
by @code{set-car!} is unspecified.
|
||
@end deffn
|
||
|
||
@rnindex set-cdr!
|
||
@deffn {Scheme Procedure} set-cdr! pair value
|
||
@deffnx {C Function} scm_set_cdr_x (pair, value)
|
||
Stores @var{value} in the cdr field of @var{pair}. The value returned
|
||
by @code{set-cdr!} is unspecified.
|
||
@end deffn
|
||
|
||
|
||
@node Lists
|
||
@subsection Lists
|
||
@tpindex Lists
|
||
|
||
A very important data type in Scheme---as well as in all other Lisp
|
||
dialects---is the data type @dfn{list}.@footnote{Strictly speaking,
|
||
Scheme does not have a real datatype @dfn{list}. Lists are made up of
|
||
@dfn{chained pairs}, and only exist by definition---a list is a chain
|
||
of pairs which looks like a list.}
|
||
|
||
This is the short definition of what a list is:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
Either the empty list @code{()},
|
||
|
||
@item
|
||
or a pair which has a list in its cdr.
|
||
@end itemize
|
||
|
||
@c FIXME::martin: Describe the pair chaining in more detail.
|
||
|
||
@c FIXME::martin: What is a proper, what an improper list?
|
||
@c What is a circular list?
|
||
|
||
@c FIXME::martin: Maybe steal some graphics from the Elisp reference
|
||
@c manual?
|
||
|
||
@menu
|
||
* List Syntax:: Writing literal lists.
|
||
* List Predicates:: Testing lists.
|
||
* List Constructors:: Creating new lists.
|
||
* List Selection:: Selecting from lists, getting their length.
|
||
* Append/Reverse:: Appending and reversing lists.
|
||
* List Modification:: Modifying existing lists.
|
||
* List Searching:: Searching for list elements
|
||
* List Mapping:: Applying procedures to lists.
|
||
@end menu
|
||
|
||
@node List Syntax
|
||
@subsubsection List Read Syntax
|
||
|
||
The syntax for lists is an opening parentheses, then all the elements of
|
||
the list (separated by whitespace) and finally a closing
|
||
parentheses.@footnote{Note that there is no separation character between
|
||
the list elements, like a comma or a semicolon.}.
|
||
|
||
@lisp
|
||
(1 2 3) ; @r{a list of the numbers 1, 2 and 3}
|
||
("foo" bar 3.1415) ; @r{a string, a symbol and a real number}
|
||
() ; @r{the empty list}
|
||
@end lisp
|
||
|
||
The last example needs a bit more explanation. A list with no elements,
|
||
called the @dfn{empty list}, is special in some ways. It is used for
|
||
terminating lists by storing it into the cdr of the last pair that makes
|
||
up a list. An example will clear that up:
|
||
|
||
@lisp
|
||
(car '(1))
|
||
@result{}
|
||
1
|
||
(cdr '(1))
|
||
@result{}
|
||
()
|
||
@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}).
|
||
|
||
|
||
@node List Predicates
|
||
@subsubsection List Predicates
|
||
|
||
Often it is useful to test whether a given Scheme object is a list or
|
||
not. List-processing procedures could use this information to test
|
||
whether their input is valid, or they could do different things
|
||
depending on the datatype of their arguments.
|
||
|
||
@rnindex list?
|
||
@deffn {Scheme Procedure} list? x
|
||
@deffnx {C Function} scm_list_p (x)
|
||
Return @code{#t} iff @var{x} is a proper list, else @code{#f}.
|
||
@end deffn
|
||
|
||
The predicate @code{null?} is often used in list-processing code to
|
||
tell whether a given list has run out of elements. That is, a loop
|
||
somehow deals with the elements of a list until the list satisfies
|
||
@code{null?}. Then, the algorithm terminates.
|
||
|
||
@rnindex null?
|
||
@deffn {Scheme Procedure} null? x
|
||
@deffnx {C Function} scm_null_p (x)
|
||
Return @code{#t} iff @var{x} is the empty list, else @code{#f}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_null (SCM x)
|
||
Return 1 when @var{x} is the empty list; otherwise return 0.
|
||
@end deftypefn
|
||
|
||
|
||
@node List Constructors
|
||
@subsubsection List Constructors
|
||
|
||
This section describes the procedures for constructing new lists.
|
||
@code{list} simply returns a list where the elements are the arguments,
|
||
@code{cons*} is similar, but the last argument is stored in the cdr of
|
||
the last pair of the list.
|
||
|
||
@c C Function scm_list(rest) used to be documented here, but it's a
|
||
@c no-op since it does nothing but return the list the caller must
|
||
@c have already created.
|
||
@c
|
||
@deffn {Scheme Procedure} list elem1 @dots{} elemN
|
||
@deffnx {C Function} scm_list_1 (elem1)
|
||
@deffnx {C Function} scm_list_2 (elem1, elem2)
|
||
@deffnx {C Function} scm_list_3 (elem1, elem2, elem3)
|
||
@deffnx {C Function} scm_list_4 (elem1, elem2, elem3, elem4)
|
||
@deffnx {C Function} scm_list_5 (elem1, elem2, elem3, elem4, elem5)
|
||
@deffnx {C Function} scm_list_n (elem1, @dots{}, elemN, @nicode{SCM_UNDEFINED})
|
||
@rnindex list
|
||
Return a new list containing elements @var{elem1} to @var{elemN}.
|
||
|
||
@code{scm_list_n} takes a variable number of arguments, terminated by
|
||
the special @code{SCM_UNDEFINED}. That final @code{SCM_UNDEFINED} is
|
||
not included in the list. None of @var{elem1} to @var{elemN} can
|
||
themselves be @code{SCM_UNDEFINED}, or @code{scm_list_n} will
|
||
terminate at that point.
|
||
@end deffn
|
||
|
||
@c C Function scm_cons_star(arg1,rest) used to be documented here,
|
||
@c but it's not really a useful interface, since it expects the
|
||
@c caller to have already consed up all but the first argument
|
||
@c already.
|
||
@c
|
||
@deffn {Scheme Procedure} cons* arg1 arg2 @dots{}
|
||
Like @code{list}, but the last arg provides the tail of the
|
||
constructed list, returning @code{(cons @var{arg1} (cons
|
||
@var{arg2} (cons @dots{} @var{argn})))}. Requires at least one
|
||
argument. If given one argument, that argument is returned as
|
||
result. This function is called @code{list*} in some other
|
||
Schemes and in Common LISP.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list-copy lst
|
||
@deffnx {C Function} scm_list_copy (lst)
|
||
Return a (newly-created) copy of @var{lst}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} make-list n [init]
|
||
Create a list containing of @var{n} elements, where each element is
|
||
initialized to @var{init}. @var{init} defaults to the empty list
|
||
@code{()} if not given.
|
||
@end deffn
|
||
|
||
Note that @code{list-copy} only makes a copy of the pairs which make up
|
||
the spine of the lists. The list elements are not copied, which means
|
||
that modifying the elements of the new list also modifies the elements
|
||
of the old list. On the other hand, applying procedures like
|
||
@code{set-cdr!} or @code{delv!} to the new list will not alter the old
|
||
list. If you also need to copy the list elements (making a deep copy),
|
||
use the procedure @code{copy-tree} (@pxref{Copying}).
|
||
|
||
@node List Selection
|
||
@subsubsection List Selection
|
||
|
||
These procedures are used to get some information about a list, or to
|
||
retrieve one or more elements of a list.
|
||
|
||
@rnindex length
|
||
@deffn {Scheme Procedure} length lst
|
||
@deffnx {C Function} scm_length (lst)
|
||
Return the number of elements in list @var{lst}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} last-pair lst
|
||
@deffnx {C Function} scm_last_pair (lst)
|
||
Return the last pair in @var{lst}, signalling an error if
|
||
@var{lst} is circular.
|
||
@end deffn
|
||
|
||
@rnindex list-ref
|
||
@deffn {Scheme Procedure} list-ref list k
|
||
@deffnx {C Function} scm_list_ref (list, k)
|
||
Return the @var{k}th element from @var{list}.
|
||
@end deffn
|
||
|
||
@rnindex list-tail
|
||
@deffn {Scheme Procedure} list-tail lst k
|
||
@deffnx {Scheme Procedure} list-cdr-ref lst k
|
||
@deffnx {C Function} scm_list_tail (lst, k)
|
||
Return the "tail" of @var{lst} beginning with its @var{k}th element.
|
||
The first element of the list is considered to be element 0.
|
||
|
||
@code{list-tail} and @code{list-cdr-ref} are identical. It may help to
|
||
think of @code{list-cdr-ref} as accessing the @var{k}th cdr of the list,
|
||
or returning the results of cdring @var{k} times down @var{lst}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list-head lst k
|
||
@deffnx {C Function} scm_list_head (lst, k)
|
||
Copy the first @var{k} elements from @var{lst} into a new list, and
|
||
return it.
|
||
@end deffn
|
||
|
||
@node Append/Reverse
|
||
@subsubsection Append and Reverse
|
||
|
||
@code{append} and @code{append!} are used to concatenate two or more
|
||
lists in order to form a new list. @code{reverse} and @code{reverse!}
|
||
return lists with the same elements as their arguments, but in reverse
|
||
order. The procedure variants with an @code{!} directly modify the
|
||
pairs which form the list, whereas the other procedures create new
|
||
pairs. This is why you should be careful when using the side-effecting
|
||
variants.
|
||
|
||
@rnindex append
|
||
@deffn {Scheme Procedure} append lst1 @dots{} lstN
|
||
@deffnx {Scheme Procedure} append! lst1 @dots{} lstN
|
||
@deffnx {C Function} scm_append (lstlst)
|
||
@deffnx {C Function} scm_append_x (lstlst)
|
||
Return a list comprising all the elements of lists @var{lst1} to
|
||
@var{lstN}.
|
||
|
||
@lisp
|
||
(append '(x) '(y)) @result{} (x y)
|
||
(append '(a) '(b c d)) @result{} (a b c d)
|
||
(append '(a (b)) '((c))) @result{} (a (b) (c))
|
||
@end lisp
|
||
|
||
The last argument @var{lstN} may actually be any object; an improper
|
||
list results if the last argument is not a proper list.
|
||
|
||
@lisp
|
||
(append '(a b) '(c . d)) @result{} (a b c . d)
|
||
(append '() 'a) @result{} a
|
||
@end lisp
|
||
|
||
@code{append} doesn't modify the given lists, but the return may share
|
||
structure with the final @var{lstN}. @code{append!} modifies the
|
||
given lists to form its return.
|
||
|
||
For @code{scm_append} and @code{scm_append_x}, @var{lstlst} is a list
|
||
of the list operands @var{lst1} @dots{} @var{lstN}. That @var{lstlst}
|
||
itself is not modified or used in the return.
|
||
@end deffn
|
||
|
||
@rnindex reverse
|
||
@deffn {Scheme Procedure} reverse lst
|
||
@deffnx {Scheme Procedure} reverse! lst [newtail]
|
||
@deffnx {C Function} scm_reverse (lst)
|
||
@deffnx {C Function} scm_reverse_x (lst, newtail)
|
||
Return a list comprising the elements of @var{lst}, in reverse order.
|
||
|
||
@code{reverse} constructs a new list, @code{reverse!} modifies
|
||
@var{lst} in constructing its return.
|
||
|
||
For @code{reverse!}, the optional @var{newtail} is appended to to the
|
||
result. @var{newtail} isn't reversed, it simply becomes the list
|
||
tail. For @code{scm_reverse_x}, the @var{newtail} parameter is
|
||
mandatory, but can be @code{SCM_EOL} if no further tail is required.
|
||
@end deffn
|
||
|
||
@node List Modification
|
||
@subsubsection List Modification
|
||
|
||
The following procedures modify an existing list, either by changing
|
||
elements of the list, or by changing the list structure itself.
|
||
|
||
@deffn {Scheme Procedure} list-set! list k val
|
||
@deffnx {C Function} scm_list_set_x (list, k, val)
|
||
Set the @var{k}th element of @var{list} to @var{val}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list-cdr-set! list k val
|
||
@deffnx {C Function} scm_list_cdr_set_x (list, k, val)
|
||
Set the @var{k}th cdr of @var{list} to @var{val}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delq item lst
|
||
@deffnx {C Function} scm_delq (item, lst)
|
||
Return a newly-created copy of @var{lst} with elements
|
||
@code{eq?} to @var{item} removed. This procedure mirrors
|
||
@code{memq}: @code{delq} compares elements of @var{lst} against
|
||
@var{item} with @code{eq?}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delv item lst
|
||
@deffnx {C Function} scm_delv (item, lst)
|
||
Return a newly-created copy of @var{lst} with elements
|
||
@code{eqv?} to @var{item} removed. This procedure mirrors
|
||
@code{memv}: @code{delv} compares elements of @var{lst} against
|
||
@var{item} with @code{eqv?}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delete item lst
|
||
@deffnx {C Function} scm_delete (item, lst)
|
||
Return a newly-created copy of @var{lst} with elements
|
||
@code{equal?} to @var{item} removed. This procedure mirrors
|
||
@code{member}: @code{delete} compares elements of @var{lst}
|
||
against @var{item} with @code{equal?}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delq! item lst
|
||
@deffnx {Scheme Procedure} delv! item lst
|
||
@deffnx {Scheme Procedure} delete! item lst
|
||
@deffnx {C Function} scm_delq_x (item, lst)
|
||
@deffnx {C Function} scm_delv_x (item, lst)
|
||
@deffnx {C Function} scm_delete_x (item, lst)
|
||
These procedures are destructive versions of @code{delq}, @code{delv}
|
||
and @code{delete}: they modify the pointers in the existing @var{lst}
|
||
rather than creating a new list. Caveat evaluator: Like other
|
||
destructive list functions, these functions cannot modify the binding of
|
||
@var{lst}, and so cannot be used to delete the first element of
|
||
@var{lst} destructively.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delq1! item lst
|
||
@deffnx {C Function} scm_delq1_x (item, lst)
|
||
Like @code{delq!}, but only deletes the first occurrence of
|
||
@var{item} from @var{lst}. Tests for equality using
|
||
@code{eq?}. See also @code{delv1!} and @code{delete1!}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delv1! item lst
|
||
@deffnx {C Function} scm_delv1_x (item, lst)
|
||
Like @code{delv!}, but only deletes the first occurrence of
|
||
@var{item} from @var{lst}. Tests for equality using
|
||
@code{eqv?}. See also @code{delq1!} and @code{delete1!}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} delete1! item lst
|
||
@deffnx {C Function} scm_delete1_x (item, lst)
|
||
Like @code{delete!}, but only deletes the first occurrence of
|
||
@var{item} from @var{lst}. Tests for equality using
|
||
@code{equal?}. See also @code{delq1!} and @code{delv1!}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} filter pred lst
|
||
@deffnx {Scheme Procedure} filter! pred lst
|
||
Return a list containing all elements from @var{lst} which satisfy the
|
||
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
|
||
@end deffn
|
||
|
||
@node List Searching
|
||
@subsubsection List Searching
|
||
|
||
The following procedures search lists for particular elements. They use
|
||
different comparison predicates for comparing list elements with the
|
||
object to be searched. When they fail, they return @code{#f}, otherwise
|
||
they return the sublist whose car is equal to the search object, where
|
||
equality depends on the equality predicate used.
|
||
|
||
@rnindex memq
|
||
@deffn {Scheme Procedure} memq x lst
|
||
@deffnx {C Function} scm_memq (x, lst)
|
||
Return the first sublist of @var{lst} whose car is @code{eq?}
|
||
to @var{x} where the sublists of @var{lst} are the non-empty
|
||
lists returned by @code{(list-tail @var{lst} @var{k})} for
|
||
@var{k} less than the length of @var{lst}. If @var{x} does not
|
||
occur in @var{lst}, then @code{#f} (not the empty list) is
|
||
returned.
|
||
@end deffn
|
||
|
||
@rnindex memv
|
||
@deffn {Scheme Procedure} memv x lst
|
||
@deffnx {C Function} scm_memv (x, lst)
|
||
Return the first sublist of @var{lst} whose car is @code{eqv?}
|
||
to @var{x} where the sublists of @var{lst} are the non-empty
|
||
lists returned by @code{(list-tail @var{lst} @var{k})} for
|
||
@var{k} less than the length of @var{lst}. If @var{x} does not
|
||
occur in @var{lst}, then @code{#f} (not the empty list) is
|
||
returned.
|
||
@end deffn
|
||
|
||
@rnindex member
|
||
@deffn {Scheme Procedure} member x lst
|
||
@deffnx {C Function} scm_member (x, lst)
|
||
Return the first sublist of @var{lst} whose car is
|
||
@code{equal?} to @var{x} where the sublists of @var{lst} are
|
||
the non-empty lists returned by @code{(list-tail @var{lst}
|
||
@var{k})} for @var{k} less than the length of @var{lst}. If
|
||
@var{x} does not occur in @var{lst}, then @code{#f} (not the
|
||
empty list) is returned.
|
||
@end deffn
|
||
|
||
|
||
@node List Mapping
|
||
@subsubsection List Mapping
|
||
|
||
List processing is very convenient in Scheme because the process of
|
||
iterating over the elements of a list can be highly abstracted. The
|
||
procedures in this section are the most basic iterating procedures for
|
||
lists. They take a procedure and one or more lists as arguments, and
|
||
apply the procedure to each element of the list. They differ in their
|
||
return value.
|
||
|
||
@rnindex map
|
||
@c begin (texi-doc-string "guile" "map")
|
||
@deffn {Scheme Procedure} map proc arg1 arg2 @dots{}
|
||
@deffnx {Scheme Procedure} map-in-order proc arg1 arg2 @dots{}
|
||
@deffnx {C Function} scm_map (proc, arg1, args)
|
||
Apply @var{proc} to each element of the list @var{arg1} (if only two
|
||
arguments are given), or to the corresponding elements of the argument
|
||
lists (if more than two arguments are given). The result(s) of the
|
||
procedure applications are saved and returned in a list. For
|
||
@code{map}, the order of procedure applications is not specified,
|
||
@code{map-in-order} applies the procedure from left to right to the list
|
||
elements.
|
||
@end deffn
|
||
|
||
@rnindex for-each
|
||
@c begin (texi-doc-string "guile" "for-each")
|
||
@deffn {Scheme Procedure} for-each proc arg1 arg2 @dots{}
|
||
Like @code{map}, but the procedure is always applied from left to right,
|
||
and the result(s) of the procedure applications are thrown away. The
|
||
return value is not specified.
|
||
@end deffn
|
||
|
||
|
||
@node Vectors
|
||
@subsection Vectors
|
||
@tpindex Vectors
|
||
|
||
Vectors are sequences of Scheme objects. Unlike lists, the length of a
|
||
vector, once the vector is created, cannot be changed. The advantage of
|
||
vectors over lists is that the time required to access one element of a vector
|
||
given its @dfn{position} (synonymous with @dfn{index}), a zero-origin number,
|
||
is constant, whereas lists have an access time linear to the position of the
|
||
accessed element in the list.
|
||
|
||
Vectors can contain any kind of Scheme object; it is even possible to
|
||
have different types of objects in the same vector. For vectors
|
||
containing vectors, you may wish to use arrays, instead. Note, too,
|
||
that vectors are the special case of one dimensional non-uniform arrays
|
||
and that most array procedures operate happily on vectors
|
||
(@pxref{Arrays}).
|
||
|
||
@menu
|
||
* Vector Syntax:: Read syntax for vectors.
|
||
* Vector Creation:: Dynamic vector creation and validation.
|
||
* Vector Accessors:: Accessing and modifying vector contents.
|
||
* Vector Accessing from C:: Ways to work with vectors from C.
|
||
@end menu
|
||
|
||
|
||
@node Vector Syntax
|
||
@subsubsection Read Syntax for Vectors
|
||
|
||
Vectors can literally be entered in source code, just like strings,
|
||
characters or some of the other data types. The read syntax for vectors
|
||
is as follows: A sharp sign (@code{#}), followed by an opening
|
||
parentheses, all elements of the vector in their respective read syntax,
|
||
and finally a closing parentheses. The following are examples of the
|
||
read syntax for vectors; where the first vector only contains numbers
|
||
and the second three different object types: a string, a symbol and a
|
||
number in hexadecimal notation.
|
||
|
||
@lisp
|
||
#(1 2 3)
|
||
#("Hello" foo #xdeadbeef)
|
||
@end lisp
|
||
|
||
Like lists, vectors have to be quoted:
|
||
|
||
@lisp
|
||
'#(a b c) @result{} #(a b c)
|
||
@end lisp
|
||
|
||
@node Vector Creation
|
||
@subsubsection Dynamic Vector Creation and Validation
|
||
|
||
Instead of creating a vector implicitly by using the read syntax just
|
||
described, you can create a vector dynamically by calling one of the
|
||
@code{vector} and @code{list->vector} primitives with the list of Scheme
|
||
values that you want to place into a vector. The size of the vector
|
||
thus created is determined implicitly by the number of arguments given.
|
||
|
||
@rnindex vector
|
||
@rnindex list->vector
|
||
@deffn {Scheme Procedure} vector . l
|
||
@deffnx {Scheme Procedure} list->vector l
|
||
@deffnx {C Function} scm_vector (l)
|
||
Return a newly allocated vector composed of the
|
||
given arguments. Analogous to @code{list}.
|
||
|
||
@lisp
|
||
(vector 'a 'b 'c) @result{} #(a b c)
|
||
@end lisp
|
||
@end deffn
|
||
|
||
The inverse operation is @code{vector->list}:
|
||
|
||
@rnindex vector->list
|
||
@deffn {Scheme Procedure} vector->list v
|
||
@deffnx {C Function} scm_vector_to_list (v)
|
||
Return a newly allocated list composed of the elements of @var{v}.
|
||
|
||
@lisp
|
||
(vector->list '#(dah dah didah)) @result{} (dah dah didah)
|
||
(list->vector '(dididit dah)) @result{} #(dididit dah)
|
||
@end lisp
|
||
@end deffn
|
||
|
||
To allocate a vector with an explicitly specified size, use
|
||
@code{make-vector}. With this primitive you can also specify an initial
|
||
value for the vector elements (the same value for all elements, that
|
||
is):
|
||
|
||
@rnindex make-vector
|
||
@deffn {Scheme Procedure} make-vector len [fill]
|
||
@deffnx {C Function} scm_make_vector (len, fill)
|
||
Return a newly allocated vector of @var{len} elements. If a
|
||
second argument is given, then each position is initialized to
|
||
@var{fill}. Otherwise the initial contents of each position is
|
||
unspecified.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} SCM scm_c_make_vector (size_t k, SCM fill)
|
||
Like @code{scm_make_vector}, but the length is given as a @code{size_t}.
|
||
@end deftypefn
|
||
|
||
To check whether an arbitrary Scheme value @emph{is} a vector, use the
|
||
@code{vector?} primitive:
|
||
|
||
@rnindex vector?
|
||
@deffn {Scheme Procedure} vector? obj
|
||
@deffnx {C Function} scm_vector_p (obj)
|
||
Return @code{#t} if @var{obj} is a vector, otherwise return
|
||
@code{#f}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_vector (SCM obj)
|
||
Return non-zero when @var{obj} is a vector, otherwise return
|
||
@code{zero}.
|
||
@end deftypefn
|
||
|
||
@node Vector Accessors
|
||
@subsubsection Accessing and Modifying Vector Contents
|
||
|
||
@code{vector-length} and @code{vector-ref} return information about a
|
||
given vector, respectively its size and the elements that are contained
|
||
in the vector.
|
||
|
||
@rnindex vector-length
|
||
@deffn {Scheme Procedure} vector-length vector
|
||
@deffnx {C Function} scm_vector_length vector
|
||
Return the number of elements in @var{vector} as an exact integer.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} size_t scm_c_vector_length (SCM v)
|
||
Return the number of elements in @var{vector} as a @code{size_t}.
|
||
@end deftypefn
|
||
|
||
@rnindex vector-ref
|
||
@deffn {Scheme Procedure} vector-ref vector k
|
||
@deffnx {C Function} scm_vector_ref vector k
|
||
Return the contents of position @var{k} of @var{vector}.
|
||
@var{k} must be a valid index of @var{vector}.
|
||
@lisp
|
||
(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8
|
||
(vector-ref '#(1 1 2 3 5 8 13 21)
|
||
(let ((i (round (* 2 (acos -1)))))
|
||
(if (inexact? i)
|
||
(inexact->exact i)
|
||
i))) @result{} 13
|
||
@end lisp
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} SCM scm_c_vector_ref (SCM v, size_t k)
|
||
Return the contents of position @var{k} (a @code{size_t}) of
|
||
@var{vector}.
|
||
@end deftypefn
|
||
|
||
A vector created by one of the dynamic vector constructor procedures
|
||
(@pxref{Vector Creation}) can be modified using the following
|
||
procedures.
|
||
|
||
@emph{NOTE:} According to R5RS, it is an error to use any of these
|
||
procedures on a literally read vector, because such vectors should be
|
||
considered as constants. Currently, however, Guile does not detect this
|
||
error.
|
||
|
||
@rnindex vector-set!
|
||
@deffn {Scheme Procedure} vector-set! vector k obj
|
||
@deffnx {C Function} scm_vector_set_x vector k obj
|
||
Store @var{obj} in position @var{k} of @var{vector}.
|
||
@var{k} must be a valid index of @var{vector}.
|
||
The value returned by @samp{vector-set!} is unspecified.
|
||
@lisp
|
||
(let ((vec (vector 0 '(2 2 2 2) "Anna")))
|
||
(vector-set! vec 1 '("Sue" "Sue"))
|
||
vec) @result{} #(0 ("Sue" "Sue") "Anna")
|
||
@end lisp
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} void scm_c_vector_set_x (SCM v, size_t k, SCM obj)
|
||
Store @var{obj} in position @var{k} (a @code{size_t}) of @var{v}.
|
||
@end deftypefn
|
||
|
||
@rnindex vector-fill!
|
||
@deffn {Scheme Procedure} vector-fill! v fill
|
||
@deffnx {C Function} scm_vector_fill_x (v, fill)
|
||
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},
|
||
to @var{vec2} starting at position @var{start2}. @var{start1} and
|
||
@var{start2} are inclusive indices; @var{end1} is exclusive.
|
||
|
||
@code{vector-move-left!} copies elements in leftmost order.
|
||
Therefore, in the case where @var{vec1} and @var{vec2} refer to the
|
||
same vector, @code{vector-move-left!} is usually appropriate when
|
||
@var{start1} is greater than @var{start2}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} vector-move-right! vec1 start1 end1 vec2 start2
|
||
@deffnx {C Function} scm_vector_move_right_x (vec1, start1, end1, vec2, start2)
|
||
Copy elements from @var{vec1}, positions @var{start1} to @var{end1},
|
||
to @var{vec2} starting at position @var{start2}. @var{start1} and
|
||
@var{start2} are inclusive indices; @var{end1} is exclusive.
|
||
|
||
@code{vector-move-right!} copies elements in rightmost order.
|
||
Therefore, in the case where @var{vec1} and @var{vec2} refer to the
|
||
same vector, @code{vector-move-right!} is usually appropriate when
|
||
@var{start1} is less than @var{start2}.
|
||
@end deffn
|
||
|
||
@node Vector Accessing from C
|
||
@subsubsection Vector Accessing from C
|
||
|
||
A vector can be read and modified from C with the functions
|
||
@code{scm_c_vector_ref} and @code{scm_c_vector_set_x}, for example. In
|
||
addition to these functions, there are two more ways to access vectors
|
||
from C that might be more efficient in certain situations: you can
|
||
restrict yourself to @dfn{simple vectors} and then use the very fast
|
||
@emph{simple vector macros}; or you can use the very general framework
|
||
for accessing all kinds of arrays (@pxref{Accessing Arrays from C}),
|
||
which is more verbose, but can deal efficiently with all kinds of
|
||
vectors (and arrays). For vectors, you can use the
|
||
@code{scm_vector_elements} and @code{scm_vector_writable_elements}
|
||
functions as shortcuts.
|
||
|
||
@deftypefn {C Function} int scm_is_simple_vector (SCM obj)
|
||
Return non-zero if @var{obj} is a simple vector, else return zero. A
|
||
simple vector is a vector that can be used with the @code{SCM_SIMPLE_*}
|
||
macros below.
|
||
|
||
The following functions are guaranteed to return simple vectors:
|
||
@code{scm_make_vector}, @code{scm_c_make_vector}, @code{scm_vector},
|
||
@code{scm_list_to_vector}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Macro} size_t SCM_SIMPLE_VECTOR_LENGTH (SCM vec)
|
||
Evaluates to the length of the simple vector @var{vec}. No type
|
||
checking is done.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Macro} SCM SCM_SIMPLE_VECTOR_REF (SCM vec, size_t idx)
|
||
Evaluates to the element at position @var{idx} in the simple vector
|
||
@var{vec}. No type or range checking is done.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Macro} void SCM_SIMPLE_VECTOR_SET_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} {const SCM *} scm_vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
Acquire<EFBFBD>a handle for the vector @var{vec} and return a pointer to the
|
||
elements of it. This pointer can only be used to read the elements of
|
||
@var{vec}. When @var{vec} is not a vector, an error is signaled. The
|
||
handle mustr eventually be released with
|
||
@code{scm_array_handle_release}.
|
||
|
||
The variables pointed to by @var{lenp} and @var{incp} are filled with
|
||
the number of elements of the vector and the increment (number of
|
||
elements) between successive elements, respectively. Successive
|
||
elements of @var{vec} need not be contiguous in their underlying
|
||
``root vector'' returned here; hence the increment is not necessarily
|
||
equal to 1 and may well be negative too (@pxref{Shared Arrays}).
|
||
|
||
The following example shows the typical way to use this function. It
|
||
creates a list of all elements of @var{vec} (in reverse order).
|
||
|
||
@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
|
||
|
||
@end deftypefn
|
||
|
||
@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 numeric vectors for signed and
|
||
unsigned 8-bit, 16-bit, 32-bit, and 64-bit integers, two sizes of
|
||
floating point values, and complex floating-point numbers of these two
|
||
sizes.
|
||
|
||
Strings could be regarded as uniform vectors of characters,
|
||
@xref{Strings}. Likewise, bit vectors could be regarded as uniform
|
||
vectors of bits, @xref{Bit Vectors}. Both are sufficiently different
|
||
from uniform numeric vectors that the procedures described here do not
|
||
apply to these two data types. However, both strings and bit vectors
|
||
are generalized vectors, @xref{Generalized Vectors}, and arrays,
|
||
@xref{Arrays}.
|
||
|
||
Uniform numeric vectors are the special case of one dimensional uniform
|
||
numeric arrays.
|
||
|
||
Uniform numeric vectors can be useful since they consume less memory
|
||
than the non-uniform, general vectors. Also, since the types they can
|
||
store correspond directly to C types, it is easier to work with them
|
||
efficiently on a low level. Consider image processing as an example,
|
||
where you want to apply a filter to some image. While you could store
|
||
the pixels of an image in a general vector and write a general
|
||
convolution function, things are much more efficient with uniform
|
||
vectors: the convolution function knows that all pixels are unsigned
|
||
8-bit values (say), and can use a very tight inner loop.
|
||
|
||
That is, when it is written in C. Functions for efficiently working
|
||
with uniform numeric vectors from C are listed at the end of this
|
||
section.
|
||
|
||
Procedures similar to the vector procedures (@pxref{Vectors}) are
|
||
provided for handling these uniform vectors, but they are distinct
|
||
datatypes and the two cannot be inter-mixed. If you want to work
|
||
primarily with uniform numeric vectors, but want to offer support for
|
||
general vectors as a convenience, you can use one of the
|
||
@code{scm_any_to_*} functions. They will coerce lists and vectors to
|
||
the given type of uniform vector. Alternatively, you can write two
|
||
versions of your code: one that is fast and works only with uniform
|
||
numeric vectors, and one that works with any kind of vector but is
|
||
slower.
|
||
|
||
One set of the procedures listed below is a generic one: it works with
|
||
all types of uniform numeric vectors. In addition to that, there is a
|
||
set of procedures for each type that only works with that type. Unless
|
||
you really need to the generality of the first set, it is best to use
|
||
the more specific functions. They might not be that much faster, but
|
||
their use can serve as a kind of declaration and makes it easier to
|
||
optimize later on.
|
||
|
||
The generic set of procedures uses @code{uniform} in its names, the
|
||
specific ones use the tag from the following table.
|
||
|
||
@table @nicode
|
||
@item u8
|
||
unsigned 8-bit integers
|
||
|
||
@item s8
|
||
signed 8-bit integers
|
||
|
||
@item u16
|
||
unsigned 16-bit integers
|
||
|
||
@item s16
|
||
signed 16-bit integers
|
||
|
||
@item u32
|
||
unsigned 32-bit integers
|
||
|
||
@item s32
|
||
signed 32-bit integers
|
||
|
||
@item u64
|
||
unsigned 64-bit integers
|
||
|
||
@item s64
|
||
signed 64-bit integers
|
||
|
||
@item f32
|
||
the C type @code{float}
|
||
|
||
@item f64
|
||
the C type @code{double}
|
||
|
||
@item c32
|
||
complex numbers in rectangular form with the real and imaginary part
|
||
being a @code{float}
|
||
|
||
@item c64
|
||
complex numbers in rectangular form with the real and imaginary part
|
||
being a @code{double}
|
||
|
||
@end table
|
||
|
||
The external representation (ie.@: read syntax) for these vectors is
|
||
similar to normal Scheme vectors, but with an additional tag from the
|
||
tabel above indiciating the vector's type. For example,
|
||
|
||
@lisp
|
||
#u16(1 2 3)
|
||
#f64(3.1415 2.71)
|
||
@end lisp
|
||
|
||
Note that the read syntax for floating-point here conflicts with
|
||
@code{#f} for false. In Standard Scheme one can write @code{(1 #f3)}
|
||
for a three element list @code{(1 #f 3)}, but for Guile @code{(1 #f3)}
|
||
is invalid. @code{(1 #f 3)} is almost certainly what one should write
|
||
anyway to make the intention clear, so this is rarely a problem.
|
||
|
||
@deffn {Scheme Procedure} uniform-vector? obj
|
||
@deffnx {Scheme Procedure} u8vector? obj
|
||
@deffnx {Scheme Procedure} s8vector? obj
|
||
@deffnx {Scheme Procedure} u16vector? obj
|
||
@deffnx {Scheme Procedure} s16vector? obj
|
||
@deffnx {Scheme Procedure} u32vector? obj
|
||
@deffnx {Scheme Procedure} s32vector? obj
|
||
@deffnx {Scheme Procedure} u64vector? obj
|
||
@deffnx {Scheme Procedure} s64vector? obj
|
||
@deffnx {Scheme Procedure} f32vector? obj
|
||
@deffnx {Scheme Procedure} f64vector? obj
|
||
@deffnx {Scheme Procedure} c32vector? obj
|
||
@deffnx {Scheme Procedure} c64vector? obj
|
||
@deffnx {C Function} scm_uniform_vector_p (obj)
|
||
@deffnx {C Function} scm_u8vector_p (obj)
|
||
@deffnx {C Function} scm_s8vector_p (obj)
|
||
@deffnx {C Function} scm_u16vector_p (obj)
|
||
@deffnx {C Function} scm_s16vector_p (obj)
|
||
@deffnx {C Function} scm_u32vector_p (obj)
|
||
@deffnx {C Function} scm_s32vector_p (obj)
|
||
@deffnx {C Function} scm_u64vector_p (obj)
|
||
@deffnx {C Function} scm_s64vector_p (obj)
|
||
@deffnx {C Function} scm_f32vector_p (obj)
|
||
@deffnx {C Function} scm_f64vector_p (obj)
|
||
@deffnx {C Function} scm_c32vector_p (obj)
|
||
@deffnx {C Function} scm_c64vector_p (obj)
|
||
Return @code{#t} if @var{obj} is a homogeneous numeric vector of the
|
||
indicated type.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} make-u8vector n [value]
|
||
@deffnx {Scheme Procedure} make-s8vector n [value]
|
||
@deffnx {Scheme Procedure} make-u16vector n [value]
|
||
@deffnx {Scheme Procedure} make-s16vector n [value]
|
||
@deffnx {Scheme Procedure} make-u32vector n [value]
|
||
@deffnx {Scheme Procedure} make-s32vector n [value]
|
||
@deffnx {Scheme Procedure} make-u64vector n [value]
|
||
@deffnx {Scheme Procedure} make-s64vector n [value]
|
||
@deffnx {Scheme Procedure} make-f32vector n [value]
|
||
@deffnx {Scheme Procedure} make-f64vector n [value]
|
||
@deffnx {Scheme Procedure} make-c32vector n [value]
|
||
@deffnx {Scheme Procedure} make-c64vector n [value]
|
||
@deffnx {C Function} scm_make_u8vector n [value]
|
||
@deffnx {C Function} scm_make_s8vector n [value]
|
||
@deffnx {C Function} scm_make_u16vector n [value]
|
||
@deffnx {C Function} scm_make_s16vector n [value]
|
||
@deffnx {C Function} scm_make_u32vector n [value]
|
||
@deffnx {C Function} scm_make_s32vector n [value]
|
||
@deffnx {C Function} scm_make_u64vector n [value]
|
||
@deffnx {C Function} scm_make_s64vector n [value]
|
||
@deffnx {C Function} scm_make_f32vector n [value]
|
||
@deffnx {C Function} scm_make_f64vector n [value]
|
||
@deffnx {C Function} scm_make_c32vector n [value]
|
||
@deffnx {C Function} scm_make_c64vector n [value]
|
||
Return a newly allocated homogeneous numeric vector holding @var{n}
|
||
elements of the indicated type. If @var{value} is given, the vector
|
||
is initialized with that value, otherwise the contents are
|
||
unspecified.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} u8vector value @dots{}
|
||
@deffnx {Scheme Procedure} s8vector value @dots{}
|
||
@deffnx {Scheme Procedure} u16vector value @dots{}
|
||
@deffnx {Scheme Procedure} s16vector value @dots{}
|
||
@deffnx {Scheme Procedure} u32vector value @dots{}
|
||
@deffnx {Scheme Procedure} s32vector value @dots{}
|
||
@deffnx {Scheme Procedure} u64vector value @dots{}
|
||
@deffnx {Scheme Procedure} s64vector value @dots{}
|
||
@deffnx {Scheme Procedure} f32vector value @dots{}
|
||
@deffnx {Scheme Procedure} f64vector value @dots{}
|
||
@deffnx {Scheme Procedure} c32vector value @dots{}
|
||
@deffnx {Scheme Procedure} c64vector value @dots{}
|
||
@deffnx {C Function} scm_u8vector (values)
|
||
@deffnx {C Function} scm_s8vector (values)
|
||
@deffnx {C Function} scm_u16vector (values)
|
||
@deffnx {C Function} scm_s16vector (values)
|
||
@deffnx {C Function} scm_u32vector (values)
|
||
@deffnx {C Function} scm_s32vector (values)
|
||
@deffnx {C Function} scm_u64vector (values)
|
||
@deffnx {C Function} scm_s64vector (values)
|
||
@deffnx {C Function} scm_f32vector (values)
|
||
@deffnx {C Function} scm_f64vector (values)
|
||
@deffnx {C Function} scm_c32vector (values)
|
||
@deffnx {C Function} scm_c64vector (values)
|
||
Return a newly allocated homogeneous numeric vector of the indicated
|
||
type, holding the given parameter @var{value}s. The vector length is
|
||
the number of parameters given.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-vector-length vec
|
||
@deffnx {Scheme Procedure} u8vector-length vec
|
||
@deffnx {Scheme Procedure} s8vector-length vec
|
||
@deffnx {Scheme Procedure} u16vector-length vec
|
||
@deffnx {Scheme Procedure} s16vector-length vec
|
||
@deffnx {Scheme Procedure} u32vector-length vec
|
||
@deffnx {Scheme Procedure} s32vector-length vec
|
||
@deffnx {Scheme Procedure} u64vector-length vec
|
||
@deffnx {Scheme Procedure} s64vector-length vec
|
||
@deffnx {Scheme Procedure} f32vector-length vec
|
||
@deffnx {Scheme Procedure} f64vector-length vec
|
||
@deffnx {Scheme Procedure} c32vector-length vec
|
||
@deffnx {Scheme Procedure} c64vector-length vec
|
||
@deffnx {C Function} scm_uniform_vector_length (vec)
|
||
@deffnx {C Function} scm_u8vector_length (vec)
|
||
@deffnx {C Function} scm_s8vector_length (vec)
|
||
@deffnx {C Function} scm_u16vector_length (vec)
|
||
@deffnx {C Function} scm_s16vector_length (vec)
|
||
@deffnx {C Function} scm_u32vector_length (vec)
|
||
@deffnx {C Function} scm_s32vector_length (vec)
|
||
@deffnx {C Function} scm_u64vector_length (vec)
|
||
@deffnx {C Function} scm_s64vector_length (vec)
|
||
@deffnx {C Function} scm_f32vector_length (vec)
|
||
@deffnx {C Function} scm_f64vector_length (vec)
|
||
@deffnx {C Function} scm_c32vector_length (vec)
|
||
@deffnx {C Function} scm_c64vector_length (vec)
|
||
Return the number of elements in @var{vec}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-vector-ref vec i
|
||
@deffnx {Scheme Procedure} u8vector-ref vec i
|
||
@deffnx {Scheme Procedure} s8vector-ref vec i
|
||
@deffnx {Scheme Procedure} u16vector-ref vec i
|
||
@deffnx {Scheme Procedure} s16vector-ref vec i
|
||
@deffnx {Scheme Procedure} u32vector-ref vec i
|
||
@deffnx {Scheme Procedure} s32vector-ref vec i
|
||
@deffnx {Scheme Procedure} u64vector-ref vec i
|
||
@deffnx {Scheme Procedure} s64vector-ref vec i
|
||
@deffnx {Scheme Procedure} f32vector-ref vec i
|
||
@deffnx {Scheme Procedure} f64vector-ref vec i
|
||
@deffnx {Scheme Procedure} c32vector-ref vec i
|
||
@deffnx {Scheme Procedure} c64vector-ref vec i
|
||
@deffnx {C Function} scm_uniform_vector_ref (vec i)
|
||
@deffnx {C Function} scm_u8vector_ref (vec i)
|
||
@deffnx {C Function} scm_s8vector_ref (vec i)
|
||
@deffnx {C Function} scm_u16vector_ref (vec i)
|
||
@deffnx {C Function} scm_s16vector_ref (vec i)
|
||
@deffnx {C Function} scm_u32vector_ref (vec i)
|
||
@deffnx {C Function} scm_s32vector_ref (vec i)
|
||
@deffnx {C Function} scm_u64vector_ref (vec i)
|
||
@deffnx {C Function} scm_s64vector_ref (vec i)
|
||
@deffnx {C Function} scm_f32vector_ref (vec i)
|
||
@deffnx {C Function} scm_f64vector_ref (vec i)
|
||
@deffnx {C Function} scm_c32vector_ref (vec i)
|
||
@deffnx {C Function} scm_c64vector_ref (vec i)
|
||
Return the element at index @var{i} in @var{vec}. The first element
|
||
in @var{vec} is index 0.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-vector-set! vec i value
|
||
@deffnx {Scheme Procedure} u8vector-set! vec i value
|
||
@deffnx {Scheme Procedure} s8vector-set! vec i value
|
||
@deffnx {Scheme Procedure} u16vector-set! vec i value
|
||
@deffnx {Scheme Procedure} s16vector-set! vec i value
|
||
@deffnx {Scheme Procedure} u32vector-set! vec i value
|
||
@deffnx {Scheme Procedure} s32vector-set! vec i value
|
||
@deffnx {Scheme Procedure} u64vector-set! vec i value
|
||
@deffnx {Scheme Procedure} s64vector-set! vec i value
|
||
@deffnx {Scheme Procedure} f32vector-set! vec i value
|
||
@deffnx {Scheme Procedure} f64vector-set! vec i value
|
||
@deffnx {Scheme Procedure} c32vector-set! vec i value
|
||
@deffnx {Scheme Procedure} c64vector-set! vec i value
|
||
@deffnx {C Function} scm_uniform_vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_u8vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_s8vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_u16vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_s16vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_u32vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_s32vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_u64vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_s64vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_f32vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_f64vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_c32vector_set_x (vec i value)
|
||
@deffnx {C Function} scm_c64vector_set_x (vec i value)
|
||
Set the element at index @var{i} in @var{vec} to @var{value}. The
|
||
first element in @var{vec} is index 0. The return value is
|
||
unspecified.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-vector->list vec
|
||
@deffnx {Scheme Procedure} u8vector->list vec
|
||
@deffnx {Scheme Procedure} s8vector->list vec
|
||
@deffnx {Scheme Procedure} u16vector->list vec
|
||
@deffnx {Scheme Procedure} s16vector->list vec
|
||
@deffnx {Scheme Procedure} u32vector->list vec
|
||
@deffnx {Scheme Procedure} s32vector->list vec
|
||
@deffnx {Scheme Procedure} u64vector->list vec
|
||
@deffnx {Scheme Procedure} s64vector->list vec
|
||
@deffnx {Scheme Procedure} f32vector->list vec
|
||
@deffnx {Scheme Procedure} f64vector->list vec
|
||
@deffnx {Scheme Procedure} c32vector->list vec
|
||
@deffnx {Scheme Procedure} c64vector->list vec
|
||
@deffnx {C Function} scm_uniform_vector_to_list (vec)
|
||
@deffnx {C Function} scm_u8vector_to_list (vec)
|
||
@deffnx {C Function} scm_s8vector_to_list (vec)
|
||
@deffnx {C Function} scm_u16vector_to_list (vec)
|
||
@deffnx {C Function} scm_s16vector_to_list (vec)
|
||
@deffnx {C Function} scm_u32vector_to_list (vec)
|
||
@deffnx {C Function} scm_s32vector_to_list (vec)
|
||
@deffnx {C Function} scm_u64vector_to_list (vec)
|
||
@deffnx {C Function} scm_s64vector_to_list (vec)
|
||
@deffnx {C Function} scm_f32vector_to_list (vec)
|
||
@deffnx {C Function} scm_f64vector_to_list (vec)
|
||
@deffnx {C Function} scm_c32vector_to_list (vec)
|
||
@deffnx {C Function} scm_c64vector_to_list (vec)
|
||
Return a newly allocated list holding all elements of @var{vec}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list->u8vector lst
|
||
@deffnx {Scheme Procedure} list->s8vector lst
|
||
@deffnx {Scheme Procedure} list->u16vector lst
|
||
@deffnx {Scheme Procedure} list->s16vector lst
|
||
@deffnx {Scheme Procedure} list->u32vector lst
|
||
@deffnx {Scheme Procedure} list->s32vector lst
|
||
@deffnx {Scheme Procedure} list->u64vector lst
|
||
@deffnx {Scheme Procedure} list->s64vector lst
|
||
@deffnx {Scheme Procedure} list->f32vector lst
|
||
@deffnx {Scheme Procedure} list->f64vector lst
|
||
@deffnx {Scheme Procedure} list->c32vector lst
|
||
@deffnx {Scheme Procedure} list->c64vector lst
|
||
@deffnx {C Function} scm_list_to_u8vector (lst)
|
||
@deffnx {C Function} scm_list_to_s8vector (lst)
|
||
@deffnx {C Function} scm_list_to_u16vector (lst)
|
||
@deffnx {C Function} scm_list_to_s16vector (lst)
|
||
@deffnx {C Function} scm_list_to_u32vector (lst)
|
||
@deffnx {C Function} scm_list_to_s32vector (lst)
|
||
@deffnx {C Function} scm_list_to_u64vector (lst)
|
||
@deffnx {C Function} scm_list_to_s64vector (lst)
|
||
@deffnx {C Function} scm_list_to_f32vector (lst)
|
||
@deffnx {C Function} scm_list_to_f64vector (lst)
|
||
@deffnx {C Function} scm_list_to_c32vector (lst)
|
||
@deffnx {C Function} scm_list_to_c64vector (lst)
|
||
Return a newly allocated homogeneous numeric vector of the indicated type,
|
||
initialized with the elements of the list @var{lst}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} any->u8vector obj
|
||
@deffnx {Scheme Procedure} any->s8vector obj
|
||
@deffnx {Scheme Procedure} any->u16vector obj
|
||
@deffnx {Scheme Procedure} any->s16vector obj
|
||
@deffnx {Scheme Procedure} any->u32vector obj
|
||
@deffnx {Scheme Procedure} any->s32vector obj
|
||
@deffnx {Scheme Procedure} any->u64vector obj
|
||
@deffnx {Scheme Procedure} any->s64vector obj
|
||
@deffnx {Scheme Procedure} any->f32vector obj
|
||
@deffnx {Scheme Procedure} any->f64vector obj
|
||
@deffnx {Scheme Procedure} any->c32vector obj
|
||
@deffnx {Scheme Procedure} any->c64vector obj
|
||
@deffnx {C Function} scm_any_to_u8vector (obj)
|
||
@deffnx {C Function} scm_any_to_s8vector (obj)
|
||
@deffnx {C Function} scm_any_to_u16vector (obj)
|
||
@deffnx {C Function} scm_any_to_s16vector (obj)
|
||
@deffnx {C Function} scm_any_to_u32vector (obj)
|
||
@deffnx {C Function} scm_any_to_s32vector (obj)
|
||
@deffnx {C Function} scm_any_to_u64vector (obj)
|
||
@deffnx {C Function} scm_any_to_s64vector (obj)
|
||
@deffnx {C Function} scm_any_to_f32vector (obj)
|
||
@deffnx {C Function} scm_any_to_f64vector (obj)
|
||
@deffnx {C Function} scm_any_to_c32vector (obj)
|
||
@deffnx {C Function} scm_any_to_c64vector (obj)
|
||
Return a (maybe newly allocated) uniform numeric vector of the indicated
|
||
type, initialized with the elements of @var{obj}, which must be a list,
|
||
a vector, or a uniform vector. When @var{obj} is already a suitable
|
||
uniform numeric vector, it is returned unchanged.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_uniform_vector (SCM uvec)
|
||
Return non-zero when @var{uvec} is a uniform numeric vector, zero
|
||
otherwise.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} SCM scm_take_u8vector (const scm_t_uint8 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_s8vector (const scm_t_int8 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_u16vector (const scm_t_uint16 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_s168vector (const scm_t_int16 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_u32vector (const scm_t_uint32 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_s328vector (const scm_t_int32 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_u64vector (const scm_t_uint64 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_s64vector (const scm_t_int64 *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_f32vector (const float *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_f64vector (const double *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_c32vector (const float *data, size_t len)
|
||
@deftypefnx {C Function} SCM scm_take_c64vector (const double *data, size_t len)
|
||
Return a new uniform numeric vector of the indicated type and length
|
||
that uses the memory pointed to by @var{data} to store its elements.
|
||
This memory will eventually be freed with @code{free}. The argument
|
||
@var{len} specifies the number of elements in @var{data}, not its size
|
||
in bytes.
|
||
|
||
The @code{c32} and @code{c64} variants take a pointer to a C array of
|
||
@code{float}s or @code{double}s. The real parts of the complex numbers
|
||
are at even indices in that array, the corresponding imaginary parts are
|
||
at the following odd index.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} size_t scm_c_uniform_vector_length (SCM uvec)
|
||
Return the number of elements of @var{uvec} as a @code{size_t}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {const void *} scm_uniform_vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_uint8 *} scm_u8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_int8 *} scm_s8vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_uint16 *} scm_u16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_int16 *} scm_s16vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_uint32 *} scm_u32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_int32 *} scm_s32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_uint64 *} scm_u64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const scm_t_int64 *} scm_s64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const float *} scm_f23vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const double *} scm_f64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const float *} scm_c32vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {const double *} scm_c64vector_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
Like @code{scm_vector_elements} (@pxref{Vector Accessing from C}), but
|
||
returns a pointer to the elements of a uniform numeric vector of the
|
||
indicated kind.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {void *} scm_uniform_vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_uint8 *} scm_u8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_int8 *} scm_s8vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_uint16 *} scm_u16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_int16 *} scm_s16vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_uint32 *} scm_u32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_int32 *} scm_s32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_uint64 *} scm_u64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {scm_t_int64 *} scm_s64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {float *} scm_f23vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {double *} scm_f64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {float *} scm_c32vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
@deftypefnx {C Function} {double *} scm_c64vector_writable_elements (SCM vec, scm_t_array_handle *handle, size_t *lenp, ssize_t *incp)
|
||
Like @code{scm_vector_writable_elements} (@pxref{Vector Accessing from
|
||
C}), but returns a pointer to the elements of a uniform numeric vector
|
||
of the indicated kind.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} uniform-vector-read! uvec [port_or_fd [start [end]]]
|
||
@deffnx {C Function} scm_uniform_vector_read_x (uvec, port_or_fd, start, end)
|
||
Fill the elements of @var{uvec} by reading
|
||
raw bytes from @var{port-or-fdes}, using host byte order.
|
||
|
||
The optional arguments @var{start} (inclusive) and @var{end}
|
||
(exclusive) allow a specified region to be read,
|
||
leaving the remainder of the vector unchanged.
|
||
|
||
When @var{port-or-fdes} is a port, all specified elements
|
||
of @var{uvec} are attempted to be read, potentially blocking
|
||
while waiting formore input or end-of-file.
|
||
When @var{port-or-fd} is an integer, a single call to
|
||
read(2) is made.
|
||
|
||
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
|
||
|
||
@noindent
|
||
Bit vectors are zero-origin, one-dimensional arrays of booleans. They
|
||
are displayed as a sequence of @code{0}s and @code{1}s prefixed by
|
||
@code{#*}, e.g.,
|
||
|
||
@example
|
||
(make-bitvector 8 #f) @result{}
|
||
#*00000000
|
||
@end example
|
||
|
||
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)
|
||
Return @code{#t} when @var{obj} is a bitvector, else
|
||
return @code{#f}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_bitvector (SCM obj)
|
||
Return @code{1} when @var{obj} is a bitvector, else return @code{0}.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} make-bitvector len [fill]
|
||
@deffnx {C Function} scm_make_bitvector (len, fill)
|
||
Create a new bitvector of length @var{len} and
|
||
optionally initialize all elements to @var{fill}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} SCM scm_c_make_bitvector (size_t len, SCM fill)
|
||
Like @code{scm_make_bitvector}, but the length is given as a
|
||
@code{size_t}.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} bitvector . bits
|
||
@deffnx {C Function} scm_bitvector (bits)
|
||
Create a new bitvector with the arguments as elements.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bitvector-length vec
|
||
@deffnx {C Function} scm_bitvector_length (vec)
|
||
Return the length of the bitvector @var{vec}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} size_t scm_c_bitvector_length (SCM vec)
|
||
Like @code{scm_bitvector_length}, but the length is returned as a
|
||
@code{size_t}.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} bitvector-ref vec idx
|
||
@deffnx {C Function} scm_bitvector_ref (vec, idx)
|
||
Return the element at index @var{idx} of the bitvector
|
||
@var{vec}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} SCM scm_c_bitvector_ref (SCM obj, size_t idx)
|
||
Return the element at index @var{idx} of the bitvector
|
||
@var{vec}.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} bitvector-set! vec idx val
|
||
@deffnx {C Function} scm_bitvector_set_x (vec, idx, val)
|
||
Set the element at index @var{idx} of the bitvector
|
||
@var{vec} when @var{val} is true, else clear it.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} SCM scm_c_bitvector_set_x (SCM obj, size_t idx, SCM val)
|
||
Set the element at index @var{idx} of the bitvector
|
||
@var{vec} when @var{val} is true, else clear it.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} bitvector-fill! vec val
|
||
@deffnx {C Function} scm_bitvector_fill_x (vec, val)
|
||
Set all elements of the bitvector
|
||
@var{vec} when @var{val} is true, else clear them.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list->bitvector list
|
||
@deffnx {C Function} scm_list_to_bitvector (list)
|
||
Return a new bitvector initialized with the elements
|
||
of @var{list}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bitvector->list vec
|
||
@deffnx {C Function} scm_bitvector_to_list (vec)
|
||
Return a new list initialized with the elements
|
||
of the bitvector @var{vec}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bit-count bool bitvector
|
||
@deffnx {C Function} scm_bit_count (bool, bitvector)
|
||
Return a count of how many entries in @var{bitvector} are equal to
|
||
@var{bool}. For example,
|
||
|
||
@example
|
||
(bit-count #f #*000111000) @result{} 6
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bit-position bool bitvector start
|
||
@deffnx {C Function} scm_bit_position (bool, bitvector, start)
|
||
Return the index of the first occurrance of @var{bool} in
|
||
@var{bitvector}, starting from @var{start}. If there is no @var{bool}
|
||
entry between @var{start} and the end of @var{bitvector}, then return
|
||
@code{#f}. For example,
|
||
|
||
@example
|
||
(bit-position #t #*000101 0) @result{} 3
|
||
(bit-position #f #*0001111 3) @result{} #f
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bit-invert! bitvector
|
||
@deffnx {C Function} scm_bit_invert_x (bitvector)
|
||
Modify @var{bitvector} by replacing each element with its negation.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bit-set*! bitvector uvec bool
|
||
@deffnx {C Function} scm_bit_set_star_x (bitvector, uvec, bool)
|
||
Set entries of @var{bitvector} to @var{bool}, with @var{uvec}
|
||
selecting the entries to change. The return value is unspecified.
|
||
|
||
If @var{uvec} is a bit vector, then those entries where it has
|
||
@code{#t} are the ones in @var{bitvector} which are set to @var{bool}.
|
||
@var{uvec} and @var{bitvector} must be the same length. When
|
||
@var{bool} is @code{#t} it's like @var{uvec} is OR'ed into
|
||
@var{bitvector}. Or when @var{bool} is @code{#f} it can be seen as an
|
||
ANDNOT.
|
||
|
||
@example
|
||
(define bv #*01000010)
|
||
(bit-set*! bv #*10010001 #t)
|
||
bv
|
||
@result{} #*11010011
|
||
@end example
|
||
|
||
If @var{uvec} is a uniform vector of unsigned long integers, then
|
||
they're indexes into @var{bitvector} which are set to @var{bool}.
|
||
|
||
@example
|
||
(define bv #*01000010)
|
||
(bit-set*! bv #u(5 2 7) #t)
|
||
bv
|
||
@result{} #*01100111
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} bit-count* bitvector uvec bool
|
||
@deffnx {C Function} scm_bit_count_star (bitvector, uvec, bool)
|
||
Return a count of how many entries in @var{bitvector} are equal to
|
||
@var{bool}, with @var{uvec} selecting the entries to consider.
|
||
|
||
@var{uvec} is interpreted in the same way as for @code{bit-set*!}
|
||
above. Namely, if @var{uvec} is a bit vector then entries which have
|
||
@code{#t} there are considered in @var{bitvector}. Or if @var{uvec}
|
||
is a uniform vector of unsigned long integers then it's the indexes in
|
||
@var{bitvector} to consider.
|
||
|
||
For example,
|
||
|
||
@example
|
||
(bit-count* #*01110111 #*11001101 #t) @result{} 3
|
||
(bit-count* #*01110111 #u(7 0 4) #f) @result{} 2
|
||
@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
|
||
|
||
Guile has a number of data types that are generally vector-like:
|
||
strings, uniform numeric vectors, bitvectors, and of course ordinary
|
||
vectors of arbitrary Scheme values. These types are disjoint: a
|
||
Scheme value belongs to at most one of the four types listed above.
|
||
|
||
If you want to gloss over this distinction and want to treat all four
|
||
types with common code, you can use the procedures in this section.
|
||
They work with the @emph{generalized vector} type, which is the union
|
||
of the four vector-like types.
|
||
|
||
@deffn {Scheme Procedure} generalized-vector? obj
|
||
@deffnx {C Function} scm_generalized_vector_p (obj)
|
||
Return @code{#t} if @var{obj} is a vector, string,
|
||
bitvector, or uniform numeric vector.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} generalized-vector-length v
|
||
@deffnx {C Function} scm_generalized_vector_length (v)
|
||
Return the length of the generalized vector @var{v}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} generalized-vector-ref v idx
|
||
@deffnx {C Function} scm_generalized_vector_ref (v, idx)
|
||
Return the element at index @var{idx} of the
|
||
generalized vector @var{v}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} generalized-vector-set! v idx val
|
||
@deffnx {C Function} scm_generalized_vector_set_x (v, idx, val)
|
||
Set the element at index @var{idx} of the
|
||
generalized vector @var{v} to @var{val}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} generalized-vector->list v
|
||
@deffnx {C Function} scm_generalized_vector_to_list (v)
|
||
Return a new list whose elements are the elements of the
|
||
generalized vector @var{v}.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_generalized_vector (SCM obj)
|
||
Return @code{1} if @var{obj} is a vector, string,
|
||
bitvector, or uniform numeric vector; else return @code{0}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} size_t scm_c_generalized_vector_length (SCM v)
|
||
Return the length of the generalized vector @var{v}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} SCM scm_c_generalized_vector_ref (SCM v, size_t idx)
|
||
Return the element at index @var{idx} of the generalized vector @var{v}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} void scm_c_generalized_vector_set_x (SCM v, size_t idx, SCM val)
|
||
Set the element at index @var{idx} of the generalized vector @var{v}
|
||
to @var{val}.
|
||
@end deftypefn
|
||
|
||
@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
|
||
|
||
@dfn{Arrays} are a collection of cells organized into an arbitrary
|
||
number of dimensions. Each cell can be accessed in constant time by
|
||
supplying an index for each dimension.
|
||
|
||
In the current implementation, an array uses a generalized vector for
|
||
the actual storage of its elements. Any kind of generalized vector
|
||
will do, so you can have arrays of uniform numeric values, arrays of
|
||
characters, arrays of bits, and of course, arrays of arbitrary Scheme
|
||
values. For example, arrays with an underlying @code{c64vector} might
|
||
be nice for digital signal processing, while arrays made from a
|
||
@code{u8vector} might be used to hold gray-scale images.
|
||
|
||
The number of dimensions of an array is called its @dfn{rank}. Thus,
|
||
a matrix is an array of rank 2, while a vector has rank 1. When
|
||
accessing an array element, you have to specify one exact integer for
|
||
each dimension. These integers are called the @dfn{indices} of the
|
||
element. An array specifies the allowed range of indices for each
|
||
dimension via an inclusive lower and upper bound. These bounds can
|
||
well be negative, but the upper bound must be greater than or equal to
|
||
the lower bound minus one. When all lower bounds of an array are
|
||
zero, it is called a @dfn{zero-origin} array.
|
||
|
||
Arrays can be of rank 0, which could be interpreted as a scalar.
|
||
Thus, a zero-rank array can store exactly one object and the list of
|
||
indices of this element is the empty list.
|
||
|
||
Arrays contain zero elements when one of their dimensions has a zero
|
||
length. These empty arrays maintain information about their shape: a
|
||
matrix with zero columns and 3 rows is different from a matrix with 3
|
||
columns and zero rows, which again is different from a vector of
|
||
length zero.
|
||
|
||
Generalized vectors, such as strings, uniform numeric vectors, bit
|
||
vectors and ordinary vectors, are the special case of one dimensional
|
||
arrays.
|
||
|
||
@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
|
||
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><:len><@@lower><:len>...
|
||
@end example
|
||
|
||
where @code{<rank>} is a positive integer in decimal giving the rank of
|
||
the array. It is omitted when the rank is 1 and the array is non-shared
|
||
and has zero-origin (see below). For shared arrays and for a non-zero
|
||
origin, the rank is always printed even when it is 1 to dinstinguish
|
||
them from ordinary vectors.
|
||
|
||
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{@@} 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
|
||
@item #(1 2 3)
|
||
is an ordinary array of rank 1 with lower bound 0 in dimension 0.
|
||
(I.e., a regular vector.)
|
||
|
||
@item #@@2(1 2 3)
|
||
is an ordinary array of rank 1 with lower bound 2 in dimension 0.
|
||
|
||
@item #2((1 2 3) (4 5 6))
|
||
is a non-uniform array of rank 2; a 3@cross{}3 matrix with index ranges 0..2
|
||
and 0..2.
|
||
|
||
@item #u32(0 1 2)
|
||
is a uniform u8 array of rank 1.
|
||
|
||
@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:
|
||
|
||
@example
|
||
(make-array 'ho 2 3) @result{} #2((ho ho ho) (ho ho ho))
|
||
@end example
|
||
|
||
The range of each dimension can also be given explicitly, e.g., another
|
||
way to create the same array:
|
||
|
||
@example
|
||
(make-array 'ho '(0 1) '(0 2)) @result{} #2((ho ho ho) (ho ho ho))
|
||
@end example
|
||
|
||
The following procedures can be used with arrays (or vectors). An
|
||
argument shown as @var{idx}@dots{} means one parameter for each
|
||
dimension in the array. A @var{idxlist} argument means a list of such
|
||
values, one for each dimension.
|
||
|
||
|
||
@deffn {Scheme Procedure} array? obj
|
||
@deffnx {C Function} scm_array_p (obj, unused)
|
||
Return @code{#t} if the @var{obj} is an array, and @code{#f} if
|
||
not.
|
||
|
||
The second argument to scm_array_p is there for historical reasons,
|
||
but it is not used. You should always pass @code{SCM_UNDEFINED} as
|
||
its value.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} typed-array? obj type
|
||
@deffnx {C Function} scm_typed_array_p (obj, type)
|
||
Return @code{#t} if the @var{obj} is an array of type @var{type}, and
|
||
@code{#f} if not.
|
||
@end deffn
|
||
|
||
@deftypefn {C Function} int scm_is_array (SCM obj)
|
||
Return @code{1} if the @var{obj} is an array and @code{0} if not.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} int scm_is_typed_array (SCM obj, SCM type)
|
||
Return @code{0} if the @var{obj} is an array of type @var{type}, and
|
||
@code{1} if not.
|
||
@end deftypefn
|
||
|
||
@deffn {Scheme Procedure} make-array fill bound @dots{}
|
||
@deffnx {C Function} scm_make_array (fill, bounds)
|
||
Equivalent to @code{(make-typed-array #t @var{fill} @var{bound} ...)}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} make-typed-array type fill bound @dots{}
|
||
@deffnx {C Function} scm_make_typed_array (type, fill, bounds)
|
||
Create and return an array that has as many dimensions as there are
|
||
@var{bound}s and (maybe) fill it with @var{fill}.
|
||
|
||
The underlaying storage vector is created according to @var{type},
|
||
which must be a symbol whose name is the `vectag' of the array as
|
||
explained above, or @code{#t} for ordinary, non-specialized arrays.
|
||
|
||
For example, using the symbol @code{f64} for @var{type} will create an
|
||
array that uses a @code{f64vector} for storing its elements, and
|
||
@code{a} will use a string.
|
||
|
||
When @var{fill} is not the special @emph{unspecified} value, the new
|
||
array is filled with @var{fill}. Otherwise, the initial contents of
|
||
the array is unspecified. The special @emph{unspecified} value is
|
||
stored in the variable @code{*unspecified*} so that for example
|
||
@code{(make-typed-array 'u32 *unspecified* 4)} creates a uninitialized
|
||
@code{u32} vector of length 4.
|
||
|
||
Each @var{bound} may be a positive non-zero integer @var{N}, in which
|
||
case the index for that dimension can range from 0 through @var{N-1}; or
|
||
an explicit index range specifier in the form @code{(LOWER UPPER)},
|
||
where both @var{lower} and @var{upper} are integers, possibly less than
|
||
zero, and possibly the same number (however, @var{lower} cannot be
|
||
greater than @var{upper}).
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list->array dimspec list
|
||
Equivalent to @code{(list->typed-array #t @var{dimspec}
|
||
@var{list})}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} list->typed-array type dimspec list
|
||
@deffnx {C Function} scm_list_to_typed_array (type, dimspec, list)
|
||
Return an array of the type indicated by @var{type} with elements the
|
||
same as those of @var{list}.
|
||
|
||
The argument @var{dimspec} determines the number of dimensions of the
|
||
array and their lower bounds. When @var{dimspec} is an exact integer,
|
||
it gives the number of dimensions directly and all lower bounds are
|
||
zero. When it is a list of exact integers, then each element is the
|
||
lower index bound of a dimension, and there will be as many dimensions
|
||
as elements in the list.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-type array
|
||
Return the type of @var{array}. This is the `vectag' used for
|
||
printing @var{array} (or @code{#t} for ordinary arrays) and can be
|
||
used with @code{make-typed-array} to create an array of the same kind
|
||
as @var{array}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-ref array idx @dots{}
|
||
Return the element at @code{(idx @dots{})} in @var{array}.
|
||
|
||
@example
|
||
(define a (make-array 999 '(1 2) '(3 4)))
|
||
(array-ref a 2 4) @result{} 999
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-in-bounds? array idx @dots{}
|
||
@deffnx {C Function} scm_array_in_bounds_p (array, idxlist)
|
||
Return @code{#t} if the given index would be acceptable to
|
||
@code{array-ref}.
|
||
|
||
@example
|
||
(define a (make-array #f '(1 2) '(3 4)))
|
||
(array-in-bounds? a 2 3) @result{} #f
|
||
(array-in-bounds? a 0 0) @result{} #f
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-set! array obj idx @dots{}
|
||
@deffnx {C Function} scm_array_set_x (array, obj, idxlist)
|
||
Set the element at @code{(idx @dots{})} in @var{array} to @var{obj}.
|
||
The return value is unspecified.
|
||
|
||
@example
|
||
(define a (make-array #f '(0 1) '(0 1)))
|
||
(array-set! a #t 1 1)
|
||
a @result{} #2((#f #f) (#f #t))
|
||
@end example
|
||
@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
|
||
the rank of @var{array}. @code{enclose-array} returns an array
|
||
resembling an array of shared arrays. The dimensions of each shared
|
||
array are the same as the @var{dim}th dimensions of the original array,
|
||
the dimensions of the outer array are the same as those of the original
|
||
array that did not match a @var{dim}.
|
||
|
||
An enclosed array is not a general Scheme array. Its elements may not
|
||
be set using @code{array-set!}. Two references to the same element of
|
||
an enclosed array will be @code{equal?} but will not in general be
|
||
@code{eq?}. The value returned by @code{array-prototype} when given an
|
||
enclosed array is unspecified.
|
||
|
||
For example,
|
||
|
||
@lisp
|
||
(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1)
|
||
@result{}
|
||
#<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>
|
||
|
||
(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0)
|
||
@result{}
|
||
#<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>
|
||
@end lisp
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-shape array
|
||
@deffnx {Scheme Procedure} array-dimensions array
|
||
@deffnx {C Function} scm_array_dimensions (array)
|
||
Return a list of the bounds for each dimenson of @var{array}.
|
||
|
||
@code{array-shape} gives @code{(@var{lower} @var{upper})} for each
|
||
dimension. @code{array-dimensions} instead returns just
|
||
@math{@var{upper}+1} for dimensions with a 0 lower bound. Both are
|
||
suitable as input to @code{make-array}.
|
||
|
||
For example,
|
||
|
||
@example
|
||
(define a (make-array 'foo '(-1 3) 5))
|
||
(array-shape a) @result{} ((-1 3) (0 4))
|
||
(array-dimensions a) @result{} ((-1 3) 5)
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-rank obj
|
||
@deffnx {C Function} scm_array_rank (obj)
|
||
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
|
||
@var{array}.
|
||
@end deffn
|
||
|
||
@c FIXME: Describe how the order affects the copying (it matters for
|
||
@c shared arrays with the same underlying root vector, presumably).
|
||
@c
|
||
@deffn {Scheme Procedure} array-copy! src dst
|
||
@deffnx {Scheme Procedure} array-copy-in-order! src dst
|
||
@deffnx {C Function} scm_array_copy_x (src, dst)
|
||
Copy every element from vector or array @var{src} to the corresponding
|
||
element of @var{dst}. @var{dst} must have the same rank as @var{src},
|
||
and be at least as large in each dimension. The return value is
|
||
unspecified.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-fill! array fill
|
||
@deffnx {C Function} scm_array_fill_x (array, fill)
|
||
Store @var{fill} in every element of @var{array}. The value returned
|
||
is unspecified.
|
||
@end deffn
|
||
|
||
@c begin (texi-doc-string "guile" "array-equal?")
|
||
@deffn {Scheme Procedure} array-equal? array1 array2 @dots{}
|
||
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
|
||
|
||
@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?
|
||
@c
|
||
@c FIXME: array-for-each doesn't say what happens if the sources have
|
||
@c different index ranges. The code currently iterates over the
|
||
@c indices of the first and expects the others to cover those. That
|
||
@c at least vaguely matches array-map!, but is is meant to be a
|
||
@c documented feature?
|
||
|
||
@deffn {Scheme Procedure} array-map! dst proc src1 @dots{} srcN
|
||
@deffnx {Scheme Procedure} array-map-in-order! dst proc src1 @dots{} srcN
|
||
@deffnx {C Function} scm_array_map_x (dst, proc, srclist)
|
||
Set each element of the @var{dst} array to values obtained from calls
|
||
to @var{proc}. The value returned is unspecified.
|
||
|
||
Each call is @code{(@var{proc} @var{elem1} @dots{} @var{elemN})},
|
||
where each @var{elem} is from the corresponding @var{src} array, at
|
||
the @var{dst} index. @code{array-map-in-order!} makes the calls in
|
||
row-major order, @code{array-map!} makes them in an unspecified order.
|
||
|
||
The @var{src} arrays must have the same number of dimensions as
|
||
@var{dst}, and must have a range for each dimension which covers the
|
||
range in @var{dst}. This ensures all @var{dst} indices are valid in
|
||
each @var{src}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-for-each proc src1 @dots{} srcN
|
||
@deffnx {C Function} scm_array_for_each (proc, src1, srclist)
|
||
Apply @var{proc} to each tuple of elements of @var{src1} @dots{}
|
||
@var{srcN}, in row-major order. The value returned is unspecified.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} array-index-map! dst proc
|
||
@deffnx {C Function} scm_array_index_map_x (dst, proc)
|
||
Set each element of the @var{dst} array to values returned by calls to
|
||
@var{proc}. The value returned is unspecified.
|
||
|
||
Each call is @code{(@var{proc} @var{i1} @dots{} @var{iN})}, where
|
||
@var{i1}@dots{}@var{iN} is the destination index, one parameter for
|
||
each dimension. The order in which the calls are made is unspecified.
|
||
|
||
For example, to create a @m{4\times4, 4x4} matrix representing a
|
||
cyclic group,
|
||
|
||
@tex
|
||
\advance\leftskip by 2\lispnarrowing {
|
||
$\left(\matrix{%
|
||
0 & 1 & 2 & 3 \cr
|
||
1 & 2 & 3 & 0 \cr
|
||
2 & 3 & 0 & 1 \cr
|
||
3 & 0 & 1 & 2 \cr
|
||
}\right)$} \par
|
||
@end tex
|
||
@ifnottex
|
||
@example
|
||
/ 0 1 2 3 \
|
||
| 1 2 3 0 |
|
||
| 2 3 0 1 |
|
||
\ 3 0 1 2 /
|
||
@end example
|
||
@end ifnottex
|
||
|
||
@example
|
||
(define a (make-array #f 4 4))
|
||
(array-index-map! a (lambda (i j)
|
||
(modulo (+ i j) 4)))
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-array-read! ra [port_or_fd [start [end]]]
|
||
@deffnx {C Function} scm_uniform_array_read_x (ra, port_or_fd, start, end)
|
||
Attempt to read all elements of @var{ura}, in lexicographic order, as
|
||
binary objects from @var{port-or-fdes}.
|
||
If an end of file is encountered,
|
||
the objects up to that point are put into @var{ura}
|
||
(starting at the beginning) and the remainder of the array is
|
||
unchanged.
|
||
|
||
The optional arguments @var{start} and @var{end} allow
|
||
a specified region of a vector (or linearized array) to be read,
|
||
leaving the remainder of the vector unchanged.
|
||
|
||
@code{uniform-array-read!} returns the number of objects read.
|
||
@var{port-or-fdes} may be omitted, in which case it defaults to the value
|
||
returned by @code{(current-input-port)}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} uniform-array-write v [port_or_fd [start [end]]]
|
||
@deffnx {C Function} scm_uniform_array_write (v, port_or_fd, start, end)
|
||
Writes all elements of @var{ura} as binary objects to
|
||
@var{port-or-fdes}.
|
||
|
||
The optional arguments @var{start}
|
||
and @var{end} allow
|
||
a specified region of a vector (or linearized array) to be written.
|
||
|
||
The number of objects actually written is returned.
|
||
@var{port-or-fdes} may be
|
||
omitted, in which case it defaults to the value returned by
|
||
@code{(current-output-port)}.
|
||
@end deffn
|
||
|
||
@node Shared Arrays
|
||
@subsubsection Shared Arrays
|
||
|
||
@deffn {Scheme Procedure} make-shared-array oldarray mapfunc bound @dots{}
|
||
@deffnx {C Function} scm_make_shared_array (oldarray, mapfunc, boundlist)
|
||
Return a new array which shares the storage of @var{oldarray}.
|
||
Changes made through either affect the same underlying storage. The
|
||
@var{bound@dots{}} arguments are the shape of the new array, the same
|
||
as @code{make-array} (@pxref{Array Procedures}).
|
||
|
||
@var{mapfunc} translates coordinates from the new array to the
|
||
@var{oldarray}. It's called as @code{(@var{mapfunc} newidx1 @dots{})}
|
||
with one parameter for each dimension of the new array, and should
|
||
return a list of indices for @var{oldarray}, one for each dimension of
|
||
@var{oldarray}.
|
||
|
||
@var{mapfunc} must be affine linear, meaning that each @var{oldarray}
|
||
index must be formed by adding integer multiples (possibly negative)
|
||
of some or all of @var{newidx1} etc, plus a possible integer offset.
|
||
The multiples and offset must be the same in each call.
|
||
|
||
@sp 1
|
||
One good use for a shared array is to restrict the range of some
|
||
dimensions, so as to apply say @code{array-for-each} or
|
||
@code{array-fill!} to only part of an array. The plain @code{list}
|
||
function can be used for @var{mapfunc} in this case, making no changes
|
||
to the index values. For example,
|
||
|
||
@example
|
||
(make-shared-array #2((a b c) (d e f) (g h i)) list 3 2)
|
||
@result{} #2((a b) (d e) (g h))
|
||
@end example
|
||
|
||
The new array can have fewer dimensions than @var{oldarray}, for
|
||
example to take a column from an array.
|
||
|
||
@example
|
||
(make-shared-array #2((a b c) (d e f) (g h i))
|
||
(lambda (i) (list i 2))
|
||
'(0 2))
|
||
@result{} #1(c f i)
|
||
@end example
|
||
|
||
A diagonal can be taken by using the single new array index for both
|
||
row and column in the old array. For example,
|
||
|
||
@example
|
||
(make-shared-array #2((a b c) (d e f) (g h i))
|
||
(lambda (i) (list i i))
|
||
'(0 2))
|
||
@result{} #1(a e i)
|
||
@end example
|
||
|
||
Dimensions can be increased by for instance considering portions of a
|
||
one dimensional array as rows in a two dimensional array.
|
||
(@code{array-contents} below can do the opposite, flattening an
|
||
array.)
|
||
|
||
@example
|
||
(make-shared-array #1(a b c d e f g h i j k l)
|
||
(lambda (i j) (list (+ (* i 3) j)))
|
||
4 3)
|
||
@result{} #2((a b c) (d e f) (g h i) (j k l))
|
||
@end example
|
||
|
||
By negating an index the order that elements appear can be reversed.
|
||
The following just reverses the column order,
|
||
|
||
@example
|
||
(make-shared-array #2((a b c) (d e f) (g h i))
|
||
(lambda (i j) (list i (- 2 j)))
|
||
3 3)
|
||
@result{} #2((c b a) (f e d) (i h g))
|
||
@end example
|
||
|
||
A fixed offset on indexes allows for instance a change from a 0 based
|
||
to a 1 based array,
|
||
|
||
@example
|
||
(define x #2((a b c) (d e f) (g h i)))
|
||
(define y (make-shared-array x
|
||
(lambda (i j) (list (1- i) (1- j)))
|
||
'(1 3) '(1 3)))
|
||
(array-ref x 0 0) @result{} a
|
||
(array-ref y 1 1) @result{} a
|
||
@end example
|
||
|
||
A multiple on an index allows every Nth element of an array to be
|
||
taken. The following is every third element,
|
||
|
||
@example
|
||
(make-shared-array #1(a b c d e f g h i j k l)
|
||
(lambda (i) (* 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 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.
|
||
|
||
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.
|
||
|
||
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 function of Guile arrays can be written as @code{p = b +
|
||
c[0]*i[0] + c[1]*i[1] + ... + c[n-1]*i[n-1]} where @code{i[k]} is the
|
||
@nicode{k}th index and @code{n} is the rank of the array. For example,
|
||
a matrix of size 3x3 would have @code{b == 0}, @code{c[0] == 3} and
|
||
@code{c[1] == 1}. When you transpose this matrix (with
|
||
@code{transpose-array}, say), you will get an array whose mapping
|
||
function has @code{b == 0}, @code{c[0] == 1} and @code{c[1] == 3}.
|
||
|
||
The function @code{scm_array_handle_dims} gives you (indirect) access to
|
||
the coefficients @code{c[k]}.
|
||
|
||
@c XXX
|
||
Note that there are no functions for accessing the elements of a
|
||
character array yet. Once the string implementation of Guile has been
|
||
changed to use Unicode, we will provide them.
|
||
|
||
@deftp {C Type} scm_t_array_handle
|
||
This is a structure type that holds all information necessary to manage
|
||
the reservation of arrays as explained above. Structures of this type
|
||
must be allocated on the stack and must only be accessed by the
|
||
functions listed below.
|
||
@end deftp
|
||
|
||
@deftypefn {C Function} void scm_array_get_handle (SCM array, scm_t_array_handle *handle)
|
||
Reserve @var{array}, which must be an array, and prepare @var{handle} to
|
||
be used with the functions below. You must eventually call
|
||
@code{scm_array_handle_release} on @var{handle}, and do this in a
|
||
properly nested fashion, as explained above. The structure pointed to
|
||
by @var{handle} does not need to be initialized before calling this
|
||
function.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} void scm_array_handle_release (scm_t_array_handle *handle)
|
||
End the array reservation represented by @var{handle}. After a call to
|
||
this function, @var{handle} might be used for another reservation.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} size_t scm_array_handle_rank (scm_t_array_handle *handle)
|
||
Return the rank of the array represented by @var{handle}.
|
||
@end deftypefn
|
||
|
||
@deftp {C Type} scm_t_array_dim
|
||
This structure type holds information about the layout of one dimension
|
||
of an array. It includes the following fields:
|
||
|
||
@table @code
|
||
@item ssize_t lbnd
|
||
@itemx ssize_t ubnd
|
||
The lower and upper bounds (both inclusive) of the permissible index
|
||
range for the given dimension. Both values can be negative, but
|
||
@var{lbnd} is always less than or equal to @var{ubnd}.
|
||
|
||
@item ssize_t inc
|
||
The distance from one element of this dimension to the next. Note, too,
|
||
that this can be negative.
|
||
@end table
|
||
@end deftp
|
||
|
||
@deftypefn {C Function} {const scm_t_array_dim *} scm_array_handle_dims (scm_t_array_handle *handle)
|
||
Return a pointer to a C vector of information about the dimensions of
|
||
the array represented by @var{handle}. This pointer is valid as long as
|
||
the array remains reserved. As explained above, the
|
||
@code{scm_t_array_dim} structures returned by this function can be used
|
||
calculate the position of an element in the storage block of the array
|
||
from its indices.
|
||
|
||
This position can then be used as an index into the C array pointer
|
||
returned by the various @code{scm_array_handle_<foo>_elements}
|
||
functions, or with @code{scm_array_handle_ref} and
|
||
@code{scm_array_handle_set}.
|
||
|
||
Here is how one can compute the position @var{pos} of an element given
|
||
its indices in the vector @var{indices}:
|
||
|
||
@example
|
||
ssize_t indices[RANK];
|
||
scm_t_array_dim *dims;
|
||
ssize_t pos;
|
||
size_t i;
|
||
|
||
pos = 0;
|
||
for (i = 0; i < RANK; i++)
|
||
@{
|
||
if (indices[i] < dims[i].lbnd || indices[i] > dims[i].ubnd)
|
||
out_of_range ();
|
||
pos += (indices[i] - dims[i].lbnd) * dims[i].inc;
|
||
@}
|
||
@end example
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} ssize_t scm_array_handle_pos (scm_t_array_handle *handle, SCM indices)
|
||
Compute the position corresponding to @var{indices}, a list of
|
||
indices. The position is computed as described above for
|
||
@code{scm_array_handle_dims}. The number of the indices and their
|
||
range is checked and an approrpiate error is signalled for invalid
|
||
indices.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} SCM scm_array_handle_ref (scm_t_array_handle *handle, ssize_t pos)
|
||
Return the element at position @var{pos} in the storage block of the
|
||
array represented by @var{handle}. Any kind of array is acceptable. No
|
||
range checking is done on @var{pos}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} void scm_array_handle_set (scm_t_array_handle *handle, ssize_t pos, SCM val)
|
||
Set the element at position @var{pos} in the storage block of the array
|
||
represented by @var{handle} to @var{val}. Any kind of array is
|
||
acceptable. No range checking is done on @var{pos}. An error is
|
||
signalled when the array can not store @var{val}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {const SCM *} scm_array_handle_elements (scm_t_array_handle *handle)
|
||
Return a pointer to the elements of a ordinary array of general Scheme
|
||
values (i.e., a non-uniform array) for reading. This pointer is valid
|
||
as long as the array remains reserved.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {SCM *} scm_array_handle_writable_elements (scm_t_array_handle *handle)
|
||
Like @code{scm_array_handle_elements}, but the pointer is good for
|
||
reading and writing.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {const void *} scm_array_handle_uniform_elements (scm_t_array_handle *handle)
|
||
Return a pointer to the elements of a uniform numeric array for reading.
|
||
This pointer is valid as long as the array remains reserved. The size
|
||
of each element is given by @code{scm_array_handle_uniform_element_size}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {void *} scm_array_handle_uniform_writable_elements (scm_t_array_handle *handle)
|
||
Like @code{scm_array_handle_uniform_elements}, but the pointer is good
|
||
reading and writing.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} size_t scm_array_handle_uniform_element_size (scm_t_array_handle *handle)
|
||
Return the size of one element of the uniform numeric array represented
|
||
by @var{handle}.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {const scm_t_uint8 *} scm_array_handle_u8_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_int8 *} scm_array_handle_s8_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_uint16 *} scm_array_handle_u16_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_int16 *} scm_array_handle_s16_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_uint32 *} scm_array_handle_u32_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_int32 *} scm_array_handle_s32_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_uint64 *} scm_array_handle_u64_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const scm_t_int64 *} scm_array_handle_s64_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const float *} scm_array_handle_f32_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const double *} scm_array_handle_f64_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const float *} scm_array_handle_c32_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {const double *} scm_array_handle_c64_elements (scm_t_array_handle *handle)
|
||
Return a pointer to the elements of a uniform numeric array of the
|
||
indicated kind for reading. This pointer is valid as long as the array
|
||
remains reserved.
|
||
|
||
The pointers for @code{c32} and @code{c64} uniform numeric arrays point
|
||
to pairs of floating point numbers. The even index holds the real part,
|
||
the odd index the imaginary part of the complex number.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {scm_t_uint8 *} scm_array_handle_u8_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_int8 *} scm_array_handle_s8_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_uint16 *} scm_array_handle_u16_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_int16 *} scm_array_handle_s16_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_uint32 *} scm_array_handle_u32_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_int32 *} scm_array_handle_s32_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_uint64 *} scm_array_handle_u64_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {scm_t_int64 *} scm_array_handle_s64_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {float *} scm_array_handle_f32_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {double *} scm_array_handle_f64_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {float *} scm_array_handle_c32_writable_elements (scm_t_array_handle *handle)
|
||
@deftypefnx {C Function} {double *} scm_array_handle_c64_writable_elements (scm_t_array_handle *handle)
|
||
Like @code{scm_array_handle_<kind>_elements}, but the pointer is good
|
||
for reading and writing.
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {const scm_t_uint32 *} scm_array_handle_bit_elements (scm_t_array_handle *handle)
|
||
Return a pointer to the words that store the bits of the represented
|
||
array, which must be a bit array.
|
||
|
||
Unlike other arrays, bit arrays have an additional offset that must be
|
||
figured into index calculations. That offset is returned by
|
||
@code{scm_array_handle_bit_elements_offset}.
|
||
|
||
To find a certain bit you first need to calculate its position as
|
||
explained above for @code{scm_array_handle_dims} and then add the
|
||
offset. This gives the absolute position of the bit, which is always a
|
||
non-negative integer.
|
||
|
||
Each word of the bit array storage block contains exactly 32 bits, with
|
||
the least significant bit in that word having the lowest absolute
|
||
position number. The next word contains the next 32 bits.
|
||
|
||
Thus, the following code can be used to access a bit whose position
|
||
according to @code{scm_array_handle_dims} is given in @var{pos}:
|
||
|
||
@example
|
||
SCM bit_array;
|
||
scm_t_array_handle handle;
|
||
scm_t_uint32 *bits;
|
||
ssize_t pos;
|
||
size_t abs_pos;
|
||
size_t word_pos, mask;
|
||
|
||
scm_array_get_handle (&bit_array, &handle);
|
||
bits = scm_array_handle_bit_elements (&handle);
|
||
|
||
pos = ...
|
||
abs_pos = pos + scm_array_handle_bit_elements_offset (&handle);
|
||
word_pos = abs_pos / 32;
|
||
mask = 1L << (abs_pos % 32);
|
||
|
||
if (bits[word_pos] & mask)
|
||
/* bit is set. */
|
||
|
||
scm_array_handle_release (&handle);
|
||
@end example
|
||
|
||
@end deftypefn
|
||
|
||
@deftypefn {C Function} {scm_t_uint32 *} scm_array_handle_bit_writable_elements (scm_t_array_handle *handle)
|
||
Like @code{scm_array_handle_bit_elements} but the pointer is good for
|
||
reading and writing. You must take care not to modify bits outside of
|
||
the allowed index range of the array, even for contiguous arrays.
|
||
@end deftypefn
|
||
|
||
@node Records
|
||
@subsection Records
|
||
|
||
A @dfn{record type} is a first class object representing a user-defined
|
||
data type. A @dfn{record} is an instance of a record type.
|
||
|
||
@deffn {Scheme Procedure} record? obj
|
||
Return @code{#t} if @var{obj} is a record of any type and @code{#f}
|
||
otherwise.
|
||
|
||
Note that @code{record?} may be true of any Scheme value; there is no
|
||
promise that records are disjoint with other Scheme types.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} make-record-type type-name field-names
|
||
Return a @dfn{record-type descriptor}, a value representing a new data
|
||
type disjoint from all others. The @var{type-name} argument must be a
|
||
string, but is only used for debugging purposes (such as the printed
|
||
representation of a record of the new type). The @var{field-names}
|
||
argument is a list of symbols naming the @dfn{fields} of a record of the
|
||
new type. It is an error if the list contains any duplicates. It is
|
||
unspecified how record-type descriptors are represented.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-constructor rtd [field-names]
|
||
Return a procedure for constructing new members of the type represented
|
||
by @var{rtd}. The returned procedure accepts exactly as many arguments
|
||
as there are symbols in the given list, @var{field-names}; these are
|
||
used, in order, as the initial values of those fields in a new record,
|
||
which is returned by the constructor procedure. The values of any
|
||
fields not named in that list are unspecified. The @var{field-names}
|
||
argument defaults to the list of field names in the call to
|
||
@code{make-record-type} that created the type represented by @var{rtd};
|
||
if the @var{field-names} argument is provided, it is an error if it
|
||
contains any duplicates or any symbols not in the default list.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-predicate rtd
|
||
Return a procedure for testing membership in the type represented by
|
||
@var{rtd}. The returned procedure accepts exactly one argument and
|
||
returns a true value if the argument is a member of the indicated record
|
||
type; it returns a false value otherwise.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-accessor rtd field-name
|
||
Return a procedure for reading the value of a particular field of a
|
||
member of the type represented by @var{rtd}. The returned procedure
|
||
accepts exactly one argument which must be a record of the appropriate
|
||
type; it returns the current value of the field named by the symbol
|
||
@var{field-name} in that record. The symbol @var{field-name} must be a
|
||
member of the list of field-names in the call to @code{make-record-type}
|
||
that created the type represented by @var{rtd}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-modifier rtd field-name
|
||
Return a procedure for writing the value of a particular field of a
|
||
member of the type represented by @var{rtd}. The returned procedure
|
||
accepts exactly two arguments: first, a record of the appropriate type,
|
||
and second, an arbitrary Scheme value; it modifies the field named by
|
||
the symbol @var{field-name} in that record to contain the given value.
|
||
The returned value of the modifier procedure is unspecified. The symbol
|
||
@var{field-name} must be a member of the list of field-names in the call
|
||
to @code{make-record-type} that created the type represented by
|
||
@var{rtd}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-type-descriptor record
|
||
Return a record-type descriptor representing the type of the given
|
||
record. That is, for example, if the returned descriptor were passed to
|
||
@code{record-predicate}, the resulting predicate would return a true
|
||
value when passed the given record. Note that it is not necessarily the
|
||
case that the returned descriptor is the one that was passed to
|
||
@code{record-constructor} in the call that created the constructor
|
||
procedure that created the given record.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-type-name rtd
|
||
Return the type-name associated with the type represented by rtd. The
|
||
returned value is @code{eqv?} to the @var{type-name} argument given in
|
||
the call to @code{make-record-type} that created the type represented by
|
||
@var{rtd}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} record-type-fields rtd
|
||
Return a list of the symbols naming the fields in members of the type
|
||
represented by @var{rtd}. The returned value is @code{equal?} to the
|
||
field-names argument given in the call to @code{make-record-type} that
|
||
created the type represented by @var{rtd}.
|
||
@end deffn
|
||
|
||
|
||
@node Structures
|
||
@subsection Structures
|
||
@tpindex Structures
|
||
|
||
[FIXME: this is pasted in from Tom Lord's original guile.texi and should
|
||
be reviewed]
|
||
|
||
A @dfn{structure type} is a first class user-defined data type. A
|
||
@dfn{structure} is an instance of a structure type. A structure type is
|
||
itself a structure.
|
||
|
||
Structures are less abstract and more general than traditional records.
|
||
In fact, in Guile Scheme, records are implemented using structures.
|
||
|
||
@menu
|
||
* Structure Concepts:: The structure of Structures
|
||
* Structure Layout:: Defining the layout of structure types
|
||
* Structure Basics:: make-, -ref and -set! procedures for structs
|
||
* Vtables:: Accessing type-specific data
|
||
@end menu
|
||
|
||
@node Structure Concepts
|
||
@subsubsection Structure Concepts
|
||
|
||
A structure object consists of a handle, structure data, and a vtable.
|
||
The handle is a Scheme value which points to both the vtable and the
|
||
structure's data. Structure data is a dynamically allocated region of
|
||
memory, private to the structure, divided up into typed fields. A
|
||
vtable is another structure used to hold type-specific data. Multiple
|
||
structures can share a common vtable.
|
||
|
||
Three concepts are key to understanding structures.
|
||
|
||
@itemize @bullet{}
|
||
@item @dfn{layout specifications}
|
||
|
||
Layout specifications determine how memory allocated to structures is
|
||
divided up into fields. Programmers must write a layout specification
|
||
whenever a new type of structure is defined.
|
||
|
||
@item @dfn{structural accessors}
|
||
|
||
Structure access is by field number. There is only one set of
|
||
accessors common to all structure objects.
|
||
|
||
@item @dfn{vtables}
|
||
|
||
Vtables, themselves structures, are first class representations of
|
||
disjoint sub-types of structures in general. In most cases, when a
|
||
new structure is created, programmers must specify a vtable for the
|
||
new structure. Each vtable has a field describing the layout of its
|
||
instances. Vtables can have additional, user-defined fields as well.
|
||
@end itemize
|
||
|
||
|
||
|
||
@node Structure Layout
|
||
@subsubsection Structure Layout
|
||
|
||
When a structure is created, a region of memory is allocated to hold its
|
||
state. The @dfn{layout} of the structure's type determines how that
|
||
memory is divided into fields.
|
||
|
||
Each field has a specified type. There are only three types allowed, each
|
||
corresponding to a one letter code. The allowed types are:
|
||
|
||
@itemize @bullet{}
|
||
@item 'u' -- unprotected
|
||
|
||
The field holds binary data that is not GC protected.
|
||
|
||
@item 'p' -- protected
|
||
|
||
The field holds a Scheme value and is GC protected.
|
||
|
||
@item 's' -- self
|
||
|
||
The field holds a Scheme value and is GC protected. When a structure is
|
||
created with this type of field, the field is initialized to refer to
|
||
the structure's own handle. This kind of field is mainly useful when
|
||
mixing Scheme and C code in which the C code may need to compute a
|
||
structure's handle given only the address of its malloc'd data.
|
||
@end itemize
|
||
|
||
|
||
Each field also has an associated access protection. There are only
|
||
three kinds of protection, each corresponding to a one letter code.
|
||
The allowed protections are:
|
||
|
||
@itemize @bullet{}
|
||
@item 'w' -- writable
|
||
|
||
The field can be read and written.
|
||
|
||
@item 'r' -- readable
|
||
|
||
The field can be read, but not written.
|
||
|
||
@item 'o' -- opaque
|
||
|
||
The field can be neither read nor written. This kind
|
||
of protection is for fields useful only to built-in routines.
|
||
@end itemize
|
||
|
||
A layout specification is described by stringing together pairs
|
||
of letters: one to specify a field type and one to specify a field
|
||
protection. For example, a traditional cons pair type object could
|
||
be described as:
|
||
|
||
@example
|
||
; cons pairs have two writable fields of Scheme data
|
||
"pwpw"
|
||
@end example
|
||
|
||
A pair object in which the first field is held constant could be:
|
||
|
||
@example
|
||
"prpw"
|
||
@end example
|
||
|
||
Binary fields, (fields of type "u"), hold one @dfn{word} each. The
|
||
size of a word is a machine dependent value defined to be equal to the
|
||
value of the C expression: @code{sizeof (long)}.
|
||
|
||
The last field of a structure layout may specify a tail array.
|
||
A tail array is indicated by capitalizing the field's protection
|
||
code ('W', 'R' or 'O'). A tail-array field is replaced by
|
||
a read-only binary data field containing an array size. The array
|
||
size is determined at the time the structure is created. It is followed
|
||
by a corresponding number of fields of the type specified for the
|
||
tail array. For example, a conventional Scheme vector can be
|
||
described as:
|
||
|
||
@example
|
||
; A vector is an arbitrary number of writable fields holding Scheme
|
||
; values:
|
||
"pW"
|
||
@end example
|
||
|
||
In the above example, field 0 contains the size of the vector and
|
||
fields beginning at 1 contain the vector elements.
|
||
|
||
A kind of tagged vector (a constant tag followed by conventional
|
||
vector elements) might be:
|
||
|
||
@example
|
||
"prpW"
|
||
@end example
|
||
|
||
|
||
Structure layouts are represented by specially interned symbols whose
|
||
name is a string of type and protection codes. To create a new
|
||
structure layout, use this procedure:
|
||
|
||
@deffn {Scheme Procedure} make-struct-layout fields
|
||
@deffnx {C Function} scm_make_struct_layout (fields)
|
||
Return a new structure layout object.
|
||
|
||
@var{fields} must be a string made up of pairs of characters
|
||
strung together. The first character of each pair describes a field
|
||
type, the second a field protection. Allowed types are 'p' for
|
||
GC-protected Scheme data, 'u' for unprotected binary data, and 's' for
|
||
a field that points to the structure itself. Allowed protections
|
||
are 'w' for mutable fields, 'r' for read-only fields, and 'o' for opaque
|
||
fields. The last field protection specification may be capitalized to
|
||
indicate that the field is a tail-array.
|
||
@end deffn
|
||
|
||
|
||
|
||
@node Structure Basics
|
||
@subsubsection Structure Basics
|
||
|
||
This section describes the basic procedures for creating and accessing
|
||
structures.
|
||
|
||
@deffn {Scheme Procedure} make-struct vtable tail_array_size . init
|
||
@deffnx {C Function} scm_make_struct (vtable, tail_array_size, init)
|
||
Create a new structure.
|
||
|
||
@var{type} must be a vtable structure (@pxref{Vtables}).
|
||
|
||
@var{tail-elts} must be a non-negative integer. If the layout
|
||
specification indicated by @var{type} includes a tail-array,
|
||
this is the number of elements allocated to that array.
|
||
|
||
The @var{init1}, @dots{} are optional arguments describing how
|
||
successive fields of the structure should be initialized. Only fields
|
||
with protection 'r' or 'w' can be initialized, except for fields of
|
||
type 's', which are automatically initialized to point to the new
|
||
structure itself; fields with protection 'o' can not be initialized by
|
||
Scheme programs.
|
||
|
||
If fewer optional arguments than initializable fields are supplied,
|
||
fields of type 'p' get default value #f while fields of type 'u' are
|
||
initialized to 0.
|
||
|
||
Structs are currently the basic representation for record-like data
|
||
structures in Guile. The plan is to eventually replace them with a
|
||
new representation which will at the same time be easier to use and
|
||
more powerful.
|
||
|
||
For more information, see the documentation for @code{make-vtable-vtable}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} struct? x
|
||
@deffnx {C Function} scm_struct_p (x)
|
||
Return @code{#t} iff @var{x} is a structure object, else
|
||
@code{#f}.
|
||
@end deffn
|
||
|
||
|
||
@deffn {Scheme Procedure} struct-ref handle pos
|
||
@deffnx {Scheme Procedure} struct-set! struct n value
|
||
@deffnx {C Function} scm_struct_ref (handle, pos)
|
||
@deffnx {C Function} scm_struct_set_x (struct, n, value)
|
||
Access (or modify) the @var{n}th field of @var{struct}.
|
||
|
||
If the field is of type 'p', then it can be set to an arbitrary value.
|
||
|
||
If the field is of type 'u', then it can only be set to a non-negative
|
||
integer value small enough to fit in one machine word.
|
||
@end deffn
|
||
|
||
|
||
|
||
@node Vtables
|
||
@subsubsection Vtables
|
||
|
||
Vtables are structures that are used to represent structure types. Each
|
||
vtable contains a layout specification in field
|
||
@code{vtable-index-layout} -- instances of the type are laid out
|
||
according to that specification. Vtables contain additional fields
|
||
which are used only internally to libguile. The variable
|
||
@code{vtable-offset-user} is bound to a field number. Vtable fields
|
||
at that position or greater are user definable.
|
||
|
||
@deffn {Scheme Procedure} struct-vtable handle
|
||
@deffnx {C Function} scm_struct_vtable (handle)
|
||
Return the vtable structure that describes the type of @var{struct}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} struct-vtable? x
|
||
@deffnx {C Function} scm_struct_vtable_p (x)
|
||
Return @code{#t} iff @var{x} is a vtable structure.
|
||
@end deffn
|
||
|
||
If you have a vtable structure, @code{V}, you can create an instance of
|
||
the type it describes by using @code{(make-struct V ...)}. But where
|
||
does @code{V} itself come from? One possibility is that @code{V} is an
|
||
instance of a user-defined vtable type, @code{V'}, so that @code{V} is
|
||
created by using @code{(make-struct V' ...)}. Another possibility is
|
||
that @code{V} is an instance of the type it itself describes. Vtable
|
||
structures of the second sort are created by this procedure:
|
||
|
||
@deffn {Scheme Procedure} make-vtable-vtable user_fields tail_array_size . init
|
||
@deffnx {C Function} scm_make_vtable_vtable (user_fields, tail_array_size, init)
|
||
Return a new, self-describing vtable structure.
|
||
|
||
@var{user-fields} is a string describing user defined fields of the
|
||
vtable beginning at index @code{vtable-offset-user}
|
||
(see @code{make-struct-layout}).
|
||
|
||
@var{tail-size} specifies the size of the tail-array (if any) of
|
||
this vtable.
|
||
|
||
@var{init1}, @dots{} are the optional initializers for the fields of
|
||
the vtable.
|
||
|
||
Vtables have one initializable system field---the struct printer.
|
||
This field comes before the user fields in the initializers passed
|
||
to @code{make-vtable-vtable} and @code{make-struct}, and thus works as
|
||
a third optional argument to @code{make-vtable-vtable} and a fourth to
|
||
@code{make-struct} when creating vtables:
|
||
|
||
If the value is a procedure, it will be called instead of the standard
|
||
printer whenever a struct described by this vtable is printed.
|
||
The procedure will be called with arguments STRUCT and PORT.
|
||
|
||
The structure of a struct is described by a vtable, so the vtable is
|
||
in essence the type of the struct. The vtable is itself a struct with
|
||
a vtable. This could go on forever if it weren't for the
|
||
vtable-vtables which are self-describing vtables, and thus terminate
|
||
the chain.
|
||
|
||
There are several potential ways of using structs, but the standard
|
||
one is to use three kinds of structs, together building up a type
|
||
sub-system: one vtable-vtable working as the root and one or several
|
||
"types", each with a set of "instances". (The vtable-vtable should be
|
||
compared to the class <class> which is the class of itself.)
|
||
|
||
@lisp
|
||
(define ball-root (make-vtable-vtable "pr" 0))
|
||
|
||
(define (make-ball-type ball-color)
|
||
(make-struct ball-root 0
|
||
(make-struct-layout "pw")
|
||
(lambda (ball port)
|
||
(format port "#<a ~A ball owned by ~A>"
|
||
(color ball)
|
||
(owner ball)))
|
||
ball-color))
|
||
(define (color ball) (struct-ref (struct-vtable ball) vtable-offset-user))
|
||
(define (owner ball) (struct-ref ball 0))
|
||
|
||
(define red (make-ball-type 'red))
|
||
(define green (make-ball-type 'green))
|
||
|
||
(define (make-ball type owner) (make-struct type 0 owner))
|
||
|
||
(define ball (make-ball green 'Nisse))
|
||
ball @result{} #<a green ball owned by Nisse>
|
||
@end lisp
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} struct-vtable-name vtable
|
||
@deffnx {C Function} scm_struct_vtable_name (vtable)
|
||
Return the name of the vtable @var{vtable}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} set-struct-vtable-name! vtable name
|
||
@deffnx {C Function} scm_set_struct_vtable_name_x (vtable, name)
|
||
Set the name of the vtable @var{vtable} to @var{name}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} struct-vtable-tag handle
|
||
@deffnx {C Function} scm_struct_vtable_tag (handle)
|
||
Return the vtable tag of the structure @var{handle}.
|
||
@end deffn
|
||
|
||
|
||
@node Dictionary Types
|
||
@subsection Dictionary Types
|
||
|
||
A @dfn{dictionary} object is a data structure used to index
|
||
information in a user-defined way. In standard Scheme, the main
|
||
aggregate data types are lists and vectors. Lists are not really
|
||
indexed at all, and vectors are indexed only by number
|
||
(e.g. @code{(vector-ref foo 5)}). Often you will find it useful
|
||
to index your data on some other type; for example, in a library
|
||
catalog you might want to look up a book by the name of its
|
||
author. Dictionaries are used to help you organize information in
|
||
such a way.
|
||
|
||
An @dfn{association list} (or @dfn{alist} for short) is a list of
|
||
key-value pairs. Each pair represents a single quantity or
|
||
object; the @code{car} of the pair is a key which is used to
|
||
identify the object, and the @code{cdr} is the object's value.
|
||
|
||
A @dfn{hash table} also permits you to index objects with
|
||
arbitrary keys, but in a way that makes looking up any one object
|
||
extremely fast. A well-designed hash system makes hash table
|
||
lookups almost as fast as conventional array or vector references.
|
||
|
||
Alists are popular among Lisp programmers because they use only
|
||
the language's primitive operations (lists, @dfn{car}, @dfn{cdr}
|
||
and the equality primitives). No changes to the language core are
|
||
necessary. Therefore, with Scheme's built-in list manipulation
|
||
facilities, it is very convenient to handle data stored in an
|
||
association list. Also, alists are highly portable and can be
|
||
easily implemented on even the most minimal Lisp systems.
|
||
|
||
However, alists are inefficient, especially for storing large
|
||
quantities of data. Because we want Guile to be useful for large
|
||
software systems as well as small ones, Guile provides a rich set
|
||
of tools for using either association lists or hash tables.
|
||
|
||
@node Association Lists
|
||
@subsection Association Lists
|
||
@tpindex Association Lists
|
||
@tpindex Alist
|
||
@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
|
||
entries in which each entry is a pair. The @dfn{key} of each entry is
|
||
the @code{car} of the pair and the @dfn{value} of each entry is the
|
||
@code{cdr}.
|
||
|
||
@example
|
||
ASSOCIATION LIST ::= '( (KEY1 . VALUE1)
|
||
(KEY2 . VALUE2)
|
||
(KEY3 . VALUE3)
|
||
@dots{}
|
||
)
|
||
@end example
|
||
|
||
@noindent
|
||
Association lists are also known, for short, as @dfn{alists}.
|
||
|
||
The structure of an association list is just one example of the infinite
|
||
number of possible structures that can be built using pairs and lists.
|
||
As such, the keys and values in an association list can be manipulated
|
||
using the general list structure procedures @code{cons}, @code{car},
|
||
@code{cdr}, @code{set-car!}, @code{set-cdr!} and so on. However,
|
||
because association lists are so useful, Guile also provides specific
|
||
procedures for manipulating them.
|
||
|
||
@menu
|
||
* Alist Key Equality::
|
||
* Adding or Setting Alist Entries::
|
||
* Retrieving Alist Entries::
|
||
* Removing Alist Entries::
|
||
* Sloppy Alist Functions::
|
||
* Alist Example::
|
||
@end menu
|
||
|
||
@node Alist Key Equality
|
||
@subsubsection Alist Key Equality
|
||
|
||
All of Guile's dedicated association list procedures, apart from
|
||
@code{acons}, come in three flavours, depending on the level of equality
|
||
that is required to decide whether an existing key in the association
|
||
list is the same as the key that the procedure call uses to identify the
|
||
required entry.
|
||
|
||
@itemize @bullet
|
||
@item
|
||
Procedures with @dfn{assq} in their name use @code{eq?} to determine key
|
||
equality.
|
||
|
||
@item
|
||
Procedures with @dfn{assv} in their name use @code{eqv?} to determine
|
||
key equality.
|
||
|
||
@item
|
||
Procedures with @dfn{assoc} in their name use @code{equal?} to
|
||
determine key equality.
|
||
@end itemize
|
||
|
||
@code{acons} is an exception because it is used to build association
|
||
lists which do not require their entries' keys to be unique.
|
||
|
||
@node Adding or Setting Alist Entries
|
||
@subsubsection Adding or Setting Alist Entries
|
||
|
||
@code{acons} adds a new entry to an association list and returns the
|
||
combined association list. The combined alist is formed by consing the
|
||
new entry onto the head of the alist specified in the @code{acons}
|
||
procedure call. So the specified alist is not modified, but its
|
||
contents become shared with the tail of the combined alist that
|
||
@code{acons} returns.
|
||
|
||
In the most common usage of @code{acons}, a variable holding the
|
||
original association list is updated with the combined alist:
|
||
|
||
@example
|
||
(set! address-list (acons name address address-list))
|
||
@end example
|
||
|
||
In such cases, it doesn't matter that the old and new values of
|
||
@code{address-list} share some of their contents, since the old value is
|
||
usually no longer independently accessible.
|
||
|
||
Note that @code{acons} adds the specified new entry regardless of
|
||
whether the alist may already contain entries with keys that are, in
|
||
some sense, the same as that of the new entry. Thus @code{acons} is
|
||
ideal for building alists where there is no concept of key uniqueness.
|
||
|
||
@example
|
||
(set! task-list (acons 3 "pay gas bill" '()))
|
||
task-list
|
||
@result{}
|
||
((3 . "pay gas bill"))
|
||
|
||
(set! task-list (acons 3 "tidy bedroom" task-list))
|
||
task-list
|
||
@result{}
|
||
((3 . "tidy bedroom") (3 . "pay gas bill"))
|
||
@end example
|
||
|
||
@code{assq-set!}, @code{assv-set!} and @code{assoc-set!} are used to add
|
||
or replace an entry in an association list where there @emph{is} a
|
||
concept of key uniqueness. If the specified association list already
|
||
contains an entry whose key is the same as that specified in the
|
||
procedure call, the existing entry is replaced by the new one.
|
||
Otherwise, the new entry is consed onto the head of the old association
|
||
list to create the combined alist. In all cases, these procedures
|
||
return the combined alist.
|
||
|
||
@code{assq-set!} and friends @emph{may} destructively modify the
|
||
structure of the old association list in such a way that an existing
|
||
variable is correctly updated without having to @code{set!} it to the
|
||
value returned:
|
||
|
||
@example
|
||
address-list
|
||
@result{}
|
||
(("mary" . "34 Elm Road") ("james" . "16 Bow Street"))
|
||
|
||
(assoc-set! address-list "james" "1a London Road")
|
||
@result{}
|
||
(("mary" . "34 Elm Road") ("james" . "1a London Road"))
|
||
|
||
address-list
|
||
@result{}
|
||
(("mary" . "34 Elm Road") ("james" . "1a London Road"))
|
||
@end example
|
||
|
||
Or they may not:
|
||
|
||
@example
|
||
(assoc-set! address-list "bob" "11 Newington Avenue")
|
||
@result{}
|
||
(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
|
||
("james" . "1a London Road"))
|
||
|
||
address-list
|
||
@result{}
|
||
(("mary" . "34 Elm Road") ("james" . "1a London Road"))
|
||
@end example
|
||
|
||
The only safe way to update an association list variable when adding or
|
||
replacing an entry like this is to @code{set!} the variable to the
|
||
returned value:
|
||
|
||
@example
|
||
(set! address-list
|
||
(assoc-set! address-list "bob" "11 Newington Avenue"))
|
||
address-list
|
||
@result{}
|
||
(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
|
||
("james" . "1a London Road"))
|
||
@end example
|
||
|
||
Because of this slight inconvenience, you may find it more convenient to
|
||
use hash tables to store dictionary data. If your application will not
|
||
be modifying the contents of an alist very often, this may not make much
|
||
difference to you.
|
||
|
||
If you need to keep the old value of an association list in a form
|
||
independent from the list that results from modification by
|
||
@code{acons}, @code{assq-set!}, @code{assv-set!} or @code{assoc-set!},
|
||
use @code{list-copy} to copy the old association list before modifying
|
||
it.
|
||
|
||
@deffn {Scheme Procedure} acons key value alist
|
||
@deffnx {C Function} scm_acons (key, value, alist)
|
||
Add a new key-value pair to @var{alist}. A new pair is
|
||
created whose car is @var{key} and whose cdr is @var{value}, and the
|
||
pair is consed onto @var{alist}, and the new list is returned. This
|
||
function is @emph{not} destructive; @var{alist} is not modified.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} assq-set! alist key val
|
||
@deffnx {Scheme Procedure} assv-set! alist key value
|
||
@deffnx {Scheme Procedure} assoc-set! alist key value
|
||
@deffnx {C Function} scm_assq_set_x (alist, key, val)
|
||
@deffnx {C Function} scm_assv_set_x (alist, key, val)
|
||
@deffnx {C Function} scm_assoc_set_x (alist, key, val)
|
||
Reassociate @var{key} in @var{alist} with @var{value}: find any existing
|
||
@var{alist} entry for @var{key} and associate it with the new
|
||
@var{value}. If @var{alist} does not contain an entry for @var{key},
|
||
add a new one. Return the (possibly new) alist.
|
||
|
||
These functions do not attempt to verify the structure of @var{alist},
|
||
and so may cause unusual results if passed an object that is not an
|
||
association list.
|
||
@end deffn
|
||
|
||
@node Retrieving Alist Entries
|
||
@subsubsection Retrieving Alist Entries
|
||
@rnindex assq
|
||
@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.
|
||
|
||
@deffn {Scheme Procedure} assq key alist
|
||
@deffnx {Scheme Procedure} assv key alist
|
||
@deffnx {Scheme Procedure} assoc key alist
|
||
@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.
|
||
|
||
@deffn {Scheme Procedure} assq-ref alist key
|
||
@deffnx {Scheme Procedure} assv-ref alist key
|
||
@deffnx {Scheme Procedure} assoc-ref alist key
|
||
@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
|
||
|
||
@lisp
|
||
(let ((ent (@var{associator} @var{key} @var{alist})))
|
||
(and ent (cdr ent)))
|
||
@end lisp
|
||
|
||
where @var{associator} is one of @code{assq}, @code{assv} or @code{assoc}.
|
||
@end deffn
|
||
|
||
@node Removing Alist Entries
|
||
@subsubsection Removing Alist Entries
|
||
|
||
To remove the element from an association list whose key matches a
|
||
specified key, use @code{assq-remove!}, @code{assv-remove!} or
|
||
@code{assoc-remove!} (depending, as usual, on the level of equality
|
||
required between the key that you specify and the keys in the
|
||
association list).
|
||
|
||
As with @code{assq-set!} and friends, the specified alist may or may not
|
||
be modified destructively, and the only safe way to update a variable
|
||
containing the alist is to @code{set!} it to the value that
|
||
@code{assq-remove!} and friends return.
|
||
|
||
@example
|
||
address-list
|
||
@result{}
|
||
(("bob" . "11 Newington Avenue") ("mary" . "34 Elm Road")
|
||
("james" . "1a London Road"))
|
||
|
||
(set! address-list (assoc-remove! address-list "mary"))
|
||
address-list
|
||
@result{}
|
||
(("bob" . "11 Newington Avenue") ("james" . "1a London Road"))
|
||
@end example
|
||
|
||
Note that, when @code{assq/v/oc-remove!} is used to modify an
|
||
association list that has been constructed only using the corresponding
|
||
@code{assq/v/oc-set!}, there can be at most one matching entry in the
|
||
alist, so the question of multiple entries being removed in one go does
|
||
not arise. If @code{assq/v/oc-remove!} is applied to an association
|
||
list that has been constructed using @code{acons}, or an
|
||
@code{assq/v/oc-set!} with a different level of equality, or any mixture
|
||
of these, it removes only the first matching entry from the alist, even
|
||
if the alist might contain further matching entries. For example:
|
||
|
||
@example
|
||
(define address-list '())
|
||
(set! address-list (assq-set! address-list "mary" "11 Elm Street"))
|
||
(set! address-list (assq-set! address-list "mary" "57 Pine Drive"))
|
||
address-list
|
||
@result{}
|
||
(("mary" . "57 Pine Drive") ("mary" . "11 Elm Street"))
|
||
|
||
(set! address-list (assoc-remove! address-list "mary"))
|
||
address-list
|
||
@result{}
|
||
(("mary" . "11 Elm Street"))
|
||
@end example
|
||
|
||
In this example, the two instances of the string "mary" are not the same
|
||
when compared using @code{eq?}, so the two @code{assq-set!} calls add
|
||
two distinct entries to @code{address-list}. When compared using
|
||
@code{equal?}, both "mary"s in @code{address-list} are the same as the
|
||
"mary" in the @code{assoc-remove!} call, but @code{assoc-remove!} stops
|
||
after removing the first matching entry that it finds, and so one of the
|
||
"mary" entries is left in place.
|
||
|
||
@deffn {Scheme Procedure} assq-remove! alist key
|
||
@deffnx {Scheme Procedure} assv-remove! alist key
|
||
@deffnx {Scheme Procedure} assoc-remove! alist key
|
||
@deffnx {C Function} scm_assq_remove_x (alist, key)
|
||
@deffnx {C Function} scm_assv_remove_x (alist, key)
|
||
@deffnx {C Function} scm_assoc_remove_x (alist, key)
|
||
Delete the first entry in @var{alist} associated with @var{key}, and return
|
||
the resulting alist.
|
||
@end deffn
|
||
|
||
@node Sloppy Alist Functions
|
||
@subsubsection Sloppy Alist Functions
|
||
|
||
@code{sloppy-assq}, @code{sloppy-assv} and @code{sloppy-assoc} behave
|
||
like the corresponding non-@code{sloppy-} procedures, except that they
|
||
return @code{#f} when the specified association list is not well-formed,
|
||
where the non-@code{sloppy-} versions would signal an error.
|
||
|
||
Specifically, there are two conditions for which the non-@code{sloppy-}
|
||
procedures signal an error, which the @code{sloppy-} procedures handle
|
||
instead by returning @code{#f}. Firstly, if the specified alist as a
|
||
whole is not a proper list:
|
||
|
||
@example
|
||
(assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
|
||
@result{}
|
||
ERROR: In procedure assoc in expression (assoc "mary" (quote #)):
|
||
ERROR: Wrong type argument in position 2 (expecting association list): ((1 . 2) ("key" . "door") . "open sesame")
|
||
|
||
(sloppy-assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
|
||
@result{}
|
||
#f
|
||
@end example
|
||
|
||
@noindent
|
||
Secondly, if one of the entries in the specified alist is not a pair:
|
||
|
||
@example
|
||
(assoc 2 '((1 . 1) 2 (3 . 9)))
|
||
@result{}
|
||
ERROR: In procedure assoc in expression (assoc 2 (quote #)):
|
||
ERROR: Wrong type argument in position 2 (expecting association list): ((1 . 1) 2 (3 . 9))
|
||
|
||
(sloppy-assoc 2 '((1 . 1) 2 (3 . 9)))
|
||
@result{}
|
||
#f
|
||
@end example
|
||
|
||
Unless you are explicitly working with badly formed association lists,
|
||
it is much safer to use the non-@code{sloppy-} procedures, because they
|
||
help to highlight coding and data errors that the @code{sloppy-}
|
||
versions would silently cover up.
|
||
|
||
@deffn {Scheme Procedure} sloppy-assq key alist
|
||
@deffnx {C Function} scm_sloppy_assq (key, alist)
|
||
Behaves like @code{assq} but does not do any error checking.
|
||
Recommended only for use in Guile internals.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} sloppy-assv key alist
|
||
@deffnx {C Function} scm_sloppy_assv (key, alist)
|
||
Behaves like @code{assv} but does not do any error checking.
|
||
Recommended only for use in Guile internals.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} sloppy-assoc key alist
|
||
@deffnx {C Function} scm_sloppy_assoc (key, alist)
|
||
Behaves like @code{assoc} but does not do any error checking.
|
||
Recommended only for use in Guile internals.
|
||
@end deffn
|
||
|
||
@node Alist Example
|
||
@subsubsection Alist Example
|
||
|
||
Here is a longer example of how alists may be used in practice.
|
||
|
||
@lisp
|
||
(define capitals '(("New York" . "Albany")
|
||
("Oregon" . "Salem")
|
||
("Florida" . "Miami")))
|
||
|
||
;; What's the capital of Oregon?
|
||
(assoc "Oregon" capitals) @result{} ("Oregon" . "Salem")
|
||
(assoc-ref capitals "Oregon") @result{} "Salem"
|
||
|
||
;; We left out South Dakota.
|
||
(set! capitals
|
||
(assoc-set! capitals "South Dakota" "Pierre"))
|
||
capitals
|
||
@result{} (("South Dakota" . "Pierre")
|
||
("New York" . "Albany")
|
||
("Oregon" . "Salem")
|
||
("Florida" . "Miami"))
|
||
|
||
;; And we got Florida wrong.
|
||
(set! capitals
|
||
(assoc-set! capitals "Florida" "Tallahassee"))
|
||
capitals
|
||
@result{} (("South Dakota" . "Pierre")
|
||
("New York" . "Albany")
|
||
("Oregon" . "Salem")
|
||
("Florida" . "Tallahassee"))
|
||
|
||
;; After Oregon secedes, we can remove it.
|
||
(set! capitals
|
||
(assoc-remove! capitals "Oregon"))
|
||
capitals
|
||
@result{} (("South Dakota" . "Pierre")
|
||
("New York" . "Albany")
|
||
("Florida" . "Tallahassee"))
|
||
@end lisp
|
||
|
||
@node Hash Tables
|
||
@subsection Hash Tables
|
||
@tpindex Hash Tables
|
||
|
||
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
|
||
elements when searching for entries, whereas hash tables can normally
|
||
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.
|
||
@end menu
|
||
|
||
|
||
@node Hash Table Examples
|
||
@subsubsection Hash Table Examples
|
||
|
||
For demonstration purposes, this section gives a few usage examples of
|
||
some hash table procedures, together with some explanation what they do.
|
||
|
||
First we start by creating a new hash table with 31 slots, and
|
||
populate it with two key/value pairs.
|
||
|
||
@lisp
|
||
(define h (make-hash-table 31))
|
||
|
||
;; This is an opaque object
|
||
h
|
||
@result{}
|
||
#<hash-table 0/31>
|
||
|
||
;; We can also use a vector of alists.
|
||
(define h (make-vector 7 '()))
|
||
|
||
h
|
||
@result{}
|
||
#(() () () () () () ())
|
||
|
||
;; Inserting into a hash table can be done with hashq-set!
|
||
(hashq-set! h 'foo "bar")
|
||
@result{}
|
||
"bar"
|
||
|
||
(hashq-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
|
||
@code{hashq-ref}, but the problem with this procedure is that you
|
||
cannot reliably determine whether a key does exists in the table. The
|
||
reason is that the procedure returns @code{#f} if the key is not in
|
||
the table, but it will return the same value if the key is in the
|
||
table and just happens to have the value @code{#f}, as you can see in
|
||
the following examples.
|
||
|
||
@lisp
|
||
(hashq-ref h 'foo)
|
||
@result{}
|
||
"bar"
|
||
|
||
(hashq-ref h 'frob)
|
||
@result{}
|
||
#f
|
||
|
||
(hashq-ref h 'not-there)
|
||
@result{}
|
||
#f
|
||
@end lisp
|
||
|
||
Better is to use the procedure @code{hashq-get-handle}, which makes a
|
||
distinction between the two cases. Just like @code{assq}, this
|
||
procedure returns a key/value-pair on success, and @code{#f} if the
|
||
key is not found.
|
||
|
||
@lisp
|
||
(hashq-get-handle h 'foo)
|
||
@result{}
|
||
(foo . "bar")
|
||
|
||
(hashq-get-handle h 'not-there)
|
||
@result{}
|
||
#f
|
||
@end lisp
|
||
|
||
There is no procedure for calculating the number of key/value-pairs in
|
||
a hash table, but @code{hash-fold} can be used for doing exactly that.
|
||
|
||
@lisp
|
||
(hash-fold (lambda (key value seed) (+ 1 seed)) 0 h)
|
||
@result{}
|
||
3
|
||
@end lisp
|
||
|
||
@node Hash Table Reference
|
||
@subsubsection Hash Table Reference
|
||
|
||
@c FIXME: Describe in broad terms what happens for resizing, and what
|
||
@c the initial size means for this.
|
||
|
||
Like the association list functions, the hash table functions come in
|
||
several varieties, according to the equality test used for the keys.
|
||
Plain @code{hash-} functions use @code{equal?}, @code{hashq-}
|
||
functions use @code{eq?}, @code{hashv-} functions use @code{eqv?}, and
|
||
the @code{hashx-} functions use an application supplied test.
|
||
|
||
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.
|
||
|
||
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 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.
|
||
|
||
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
|
||
(@pxref{Retrieving Alist Entries}). Here's an example of such
|
||
functions implementing case-insensitive hashing of string keys,
|
||
|
||
@example
|
||
(use-modules (srfi srfi-1)
|
||
(srfi srfi-13))
|
||
|
||
(define (my-hash str size)
|
||
(remainder (string-hash-ci str) size))
|
||
(define (my-assoc str alist)
|
||
(find (lambda (pair) (string-ci=? str (car pair))) alist))
|
||
|
||
(define my-table (make-hash-table))
|
||
(hashx-set! my-hash my-assoc my-table "foo" 123)
|
||
|
||
(hashx-ref my-hash my-assoc my-table "FOO")
|
||
@result{} 123
|
||
@end example
|
||
|
||
In a @code{hashx-} @var{hash} function the aim is to spread keys
|
||
across the vector, so bucket lists don't become long. But the actual
|
||
values are arbitrary as long as they're in the range 0 to
|
||
@math{@var{size}-1}. Helpful functions for forming a hash value, in
|
||
addition to @code{hashq} etc below, include @code{symbol-hash}
|
||
(@pxref{Symbol Keys}), @code{string-hash} and @code{string-hash-ci}
|
||
(@pxref{String Comparison}), and @code{char-set-hash}
|
||
(@pxref{Character Set Predicates/Comparison}).
|
||
|
||
@sp 1
|
||
@deffn {Scheme Procedure} make-hash-table [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.
|
||
If an application knows roughly how many entries the table will hold
|
||
then it can use @var{size} to avoid rehashing when initial entries are
|
||
added.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-table? obj
|
||
@deffnx {C Function} scm_hash_table_p (obj)
|
||
Return @code{#t} if @var{obj} is a abstract hash table object.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-clear! table
|
||
@deffnx {C Function} scm_hash_clear_x (table)
|
||
Remove all items from @var{table} (without triggering a resize).
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-ref table key [dflt]
|
||
@deffnx {Scheme Procedure} hashq-ref table key [dflt]
|
||
@deffnx {Scheme Procedure} hashv-ref table key [dflt]
|
||
@deffnx {Scheme Procedure} hashx-ref hash assoc table key [dflt]
|
||
@deffnx {C Function} scm_hash_ref (table, key, dflt)
|
||
@deffnx {C Function} scm_hashq_ref (table, key, dflt)
|
||
@deffnx {C Function} scm_hashv_ref (table, key, dflt)
|
||
@deffnx {C Function} scm_hashx_ref (hash, assoc, table, key, dflt)
|
||
Lookup @var{key} in the given hash @var{table}, and return the
|
||
associated value. If @var{key} is not found, return @var{dflt}, or
|
||
@code{#f} if @var{dflt} is not given.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-set! table key val
|
||
@deffnx {Scheme Procedure} hashq-set! table key val
|
||
@deffnx {Scheme Procedure} hashv-set! table key val
|
||
@deffnx {Scheme Procedure} hashx-set! hash assoc table key val
|
||
@deffnx {C Function} scm_hash_set_x (table, key, val)
|
||
@deffnx {C Function} scm_hashq_set_x (table, key, val)
|
||
@deffnx {C Function} scm_hashv_set_x (table, key, val)
|
||
@deffnx {C Function} scm_hashx_set_x (hash, assoc, table, key, val)
|
||
Associate @var{val} with @var{key} in the given hash @var{table}. If
|
||
@var{key} is already present then it's associated value is changed.
|
||
If it's not present then a new entry is created.
|
||
@end deffn
|
||
|
||
@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
|
||
|
||
@deffn {Scheme Procedure} hash key size
|
||
@deffnx {Scheme Procedure} hashq key size
|
||
@deffnx {Scheme Procedure} hashv key size
|
||
@deffnx {C Function} scm_hash (key, size)
|
||
@deffnx {C Function} scm_hashq (key, size)
|
||
@deffnx {C Function} scm_hashv (key, size)
|
||
Return a hash value for @var{key}. This is a number in the range
|
||
@math{0} to @math{@var{size}-1}, which is suitable for use in a hash
|
||
table of the given @var{size}.
|
||
|
||
Note that @code{hashq} and @code{hashv} may use internal addresses of
|
||
objects, so if an object is garbage collected and re-created it can
|
||
have a different hash value, even when the two are notionally
|
||
@code{eq?}. For instance with symbols,
|
||
|
||
@example
|
||
(hashq 'something 123) @result{} 19
|
||
(gc)
|
||
(hashq 'something 123) @result{} 62
|
||
@end example
|
||
|
||
In normal use this is not a problem, since an object entered into a
|
||
hash table won't be garbage collected until removed. It's only if
|
||
hashing calculations are somehow separated from normal references that
|
||
its lifetime needs to be considered.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-get-handle table key
|
||
@deffnx {Scheme Procedure} hashq-get-handle table key
|
||
@deffnx {Scheme Procedure} hashv-get-handle table key
|
||
@deffnx {Scheme Procedure} hashx-get-handle hash assoc table key
|
||
@deffnx {C Function} scm_hash_get_handle (table, key)
|
||
@deffnx {C Function} scm_hashq_get_handle (table, key)
|
||
@deffnx {C Function} scm_hashv_get_handle (table, key)
|
||
@deffnx {C Function} scm_hashx_get_handle (hash, assoc, table, key)
|
||
Return the @code{(@var{key} . @var{value})} pair for @var{key} in the
|
||
given hash @var{table}, or @code{#f} if @var{key} is not in
|
||
@var{table}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-create-handle! table key init
|
||
@deffnx {Scheme Procedure} hashq-create-handle! table key init
|
||
@deffnx {Scheme Procedure} hashv-create-handle! table key init
|
||
@deffnx {Scheme Procedure} hashx-create-handle! hash assoc table key init
|
||
@deffnx {C Function} scm_hash_create_handle_x (table, key, init)
|
||
@deffnx {C Function} scm_hashq_create_handle_x (table, key, init)
|
||
@deffnx {C Function} scm_hashv_create_handle_x (table, key, init)
|
||
@deffnx {C Function} scm_hashx_create_handle_x (hash, assoc, table, key, init)
|
||
Return the @code{(@var{key} . @var{value})} pair for @var{key} in the
|
||
given hash @var{table}. If @var{key} is not in @var{table} then
|
||
create an entry for it with @var{init} as the value, and return that
|
||
pair.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-map->list proc table
|
||
@deffnx {Scheme Procedure} hash-for-each proc table
|
||
@deffnx {C Function} scm_hash_map_to_list (proc, table)
|
||
@deffnx {C Function} scm_hash_for_each (proc, table)
|
||
Apply @var{proc} to the entries in the given hash @var{table}. Each
|
||
call is @code{(@var{proc} @var{key} @var{value})}. @code{hash-map->list}
|
||
returns a list of the results from these calls, @code{hash-for-each}
|
||
discards the results and returns an unspecified value.
|
||
|
||
Calls are made over the table entries in an unspecified order, and for
|
||
@code{hash-map->list} the order of the values in the returned list is
|
||
unspecified. Results will be unpredictable if @var{table} is modified
|
||
while iterating.
|
||
|
||
For example the following returns a new alist comprising all the
|
||
entries from @code{mytable}, in no particular order.
|
||
|
||
@example
|
||
(hash-map->list cons mytable)
|
||
@end example
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-for-each-handle proc table
|
||
@deffnx {C Function} scm_hash_for_each_handle (proc, table)
|
||
Apply @var{proc} to the entries in the given hash @var{table}. Each
|
||
call is @code{(@var{proc} @var{handle})}, where @var{handle} is a
|
||
@code{(@var{key} . @var{value})} pair. Return an unspecified value.
|
||
|
||
@code{hash-for-each-handle} differs from @code{hash-for-each} only in
|
||
the argument list of @var{proc}.
|
||
@end deffn
|
||
|
||
@deffn {Scheme Procedure} hash-fold proc init table
|
||
@deffnx {C Function} scm_hash_fold (proc, init, table)
|
||
Accumulate a result by applying @var{proc} to the elements of the
|
||
given hash @var{table}. Each call is @code{(@var{proc} @var{key}
|
||
@var{value} @var{prior-result})}, where @var{key} and @var{value} are
|
||
from the @var{table} and @var{prior-result} is the return from the
|
||
previous @var{proc} call. For the first call, @var{prior-result} is
|
||
the given @var{init} value.
|
||
|
||
Calls are made over the table entries in an unspecified order.
|
||
Results will be unpredictable if @var{table} is modified while
|
||
@code{hash-fold} is running.
|
||
|
||
For example, the following returns a count of how many keys in
|
||
@code{mytable} are strings.
|
||
|
||
@example
|
||
(hash-fold (lambda (key value prior)
|
||
(if (string? key) (1+ prior) prior))
|
||
0 mytable)
|
||
@end example
|
||
@end deffn
|
||
|
||
|
||
@c Local Variables:
|
||
@c TeX-master: "guile.texi"
|
||
@c End:
|