A sequence is a generalized list, consisting of zero or more values.
You can choose between a number of different kinds of sequence implementations.
Scheme traditionally has lists and vectors.
Any Java class that implements java.util.List
is a sequence type.
Raw Java arrays can also be viewerd as a sequence,
and strings can be viewed a sequence (or vector) of characters.
Kawa also provides uniform vectors.
Sequence types differ in their API, but given a sequence type stype
you can construct instances of that types using the syntax:
(stype
v0
v1
....vn
)
For example:
(bytevector 9 8 7 6) ⇒ #u8(9 8 7 6)
For a raw Java class name jname
you may need to use
the empty keyword ||:
to separate constructor parameters (if any)
from sequence elements, as in:
(gnu.lists.U8Vector ||: 9 8 7 6) ⇒ #u8(9 8 7 6)
This syntax works with any type with a default constructor
and a 1-argument add
method;
see the section called “Allocating objects” for details.
You can use the same syntax for allocating arrays,
though array creation supports more options.
To extract an element from Scheme sequence of type stype
there is usually a function
. For example:
stype
-ref
(define vec1 (vector 5 6 7 8)) (vector-ref vec1 2) ⇒ 7
More concisely, you can use (Kawa-specific) function call syntax:
(vec1 3) ⇒ 8
The same function call syntax also works for raw Java arrays:
(define arr1 (long[] 4 5 6 7)) (arr1 3) ⇒ 7
To assign to (replace) an element from a sequence of Scheme type stype
there is usually a function
:
stype
-set!
(vector-set! vec1 1 9) vec1 ⇒ #(5 9 7 8)
Again, you can use the function call syntax:
(set! (vec1 2) 'x) vec1 ⇒ #(5 9 x 8)
A pair (sometimes called a dotted pair) is a record structure
with two fields called the car and cdr fields (for historical
reasons). Pairs are created by the procedure cons
. The
car and cdr fields are accessed by the procedures car
and
cdr
. The car and cdr fields are assigned by the procedures
set-car!
and set-cdr!
.
Pairs are used primarily to represent lists. A list can be
defined recursively as either the empty list or a pair whose
cdr is a list. More precisely, the set of lists is defined as
the smallest set X
such that:
The empty list is in
X
.If
list
is inX
, then any pair whose cdr field containslist
is also inX
.
The objects in the car fields of successive pairs of a list are the elements of the list. For example, a two-element list is a pair whose car is the first element and whose cdr is a pair whose car is the second element and whose cdr is the empty list. The length of a list is the number of elements, which is the same as the number of pairs.
The empty list is a special object of its own type. It is not a pair, it has no elements, and its length is zero.
Note: The above definitions imply that all lists have finite length and are terminated by the empty list.
The most general notation (external representation) for
Scheme pairs is the “dotted” notation (
where c1
. c2
)c1
is the value of the car field and
c2
is the value of the cdr field.
For example (4 . 5)
is a pair whose car is 4 and
whose cdr is 5. Note that (4 . 5)
is the external representation
of a pair, not an expression that evaluates to a pair.
A more streamlined notation can be used for lists: the
elements of the list are simply enclosed in parentheses and
separated by spaces. The empty list is written ()
.
For example,
(a b c d e)
and
(a . (b . (c . (d . (e . ())))))
are equivalent notations for a list of symbols.
A chain of pairs not ending in the empty list is called an improper list. Note that an improper list is not a list. The list and dotted notations can be combined to represent improper lists:
(a b c . d)
is equivalent to
(a . (b . (c . d)))
Needs to finish merging from R7RS!
Returns a newly allocated list of
k
elements. If a second argument is given, the each element is initialized tofill
. Otherwise the initial contents of each element is unspecified.(make-list 2 3) ⇒ (3 3)
The SRFI-1 List Library
is available, though not enabled by default. To use its functions you
must (require 'list-lib)
or (require 'srfi-1)
.
(require 'list-lib) (iota 5 0 -0.5) ⇒ (0.0 -0.5 -1.0 -1.5 -2.0)
Vectors are heterogeneous structures whose elements are indexed by integers. A vector typically occupies less space than a list of the same length, and the average time needed to access a randomly chosen element is typically less for the vector than for the list.
The length of a vector is the number of elements that it contains. This number is a non–negative integer that is fixed when the vector is created. The valid indices of a vector are the exact non–negative integer objects less than the length of the vector. The first element in a vector is indexed by zero, and the last element is indexed by one less than the length of the vector.
Vectors are written using the notation #(
.
For example, a vector of length 3 3 containing the number zero
in element 0, the list obj
...)(2 2 2 2)
in element 1, and the
string "Anna"
in element 2 can be written as following:
#(0 (2 2 2 2) "Anna")
Note that this is the external representation of a vector. In Kawa, a vector datum is self-evaluating, but for style (and compatibility with R7RS) is is suggested you quote a vector constant:
’#(0 (2 2 2 2) "Anna") ⇒ #(0 (2 2 2 2) "Anna")
Compare these different ways of creating a vector:
(vector a b c)
In this case
a
,b
, andc
are expressions evaluated at run-time and the results used to initialize a newly-allocated 3-element vector.[a b c]
Same as using vector, but more concise, and results in an immutable (non-modifiable) vector.
#(a b c)
This is reader syntax and creates a vector literal, at read-time, early in compile-time. The symbols
a
,b
, andc
are not evaluated but instead used literally.`#(,a ,b ,c)
This is reader-syntax, using quasi-quotation, so
a
,b
, andc
are expressions evaluated at run-time. This is equivalent to[a b c]
in that it results in an immutable vector.
Return a newly allocated vector whose elements contain the given arguments. Analogous to
list
.(vector 'a 'b 'c) ⇒ #(a b c)Alternatively, you can use square-bracket syntax, which results in an immutable vector:
['a 'b 'c] ⇒ #(a b c)
Return a newly allocated vector of
k
elements. If a second argument is given, then each element is initialized tofill
. Otherwise the initial contents of each element is#!null
.
It is an error if
k
is not a valid index ofvector
. Thevector-ref
procedure returns the contents of elementk
ofvector
.(vector-ref '#(1 1 2 3 5 8 13 21) 5) ⇒ 8 (vector-ref '#(1 1 2 3 5 8 13 21) (inexact->exact (round (* 2 (acos -1))))) ⇒ 13
It is an error if
k
is not a valid index ofvector
. Thevector-set!
procedure storesobj
in elementk
ofvector
, and returns no values.(let ((vec (vector 0 '(2 2 2 2) "Anna"))) (vector-set! vec 1 '("Sue" "Sue")) vec) ⇒ #(0 ("Sue" "Sue") "Anna") (vector-set! '#(0 1 2) 1 "doe") ⇒ error ;; constant vector
A concise alternative to vector-ref
and vector-set!
is to use function call syntax. For example:
(let ((vec (vector 0 '(2 2 2 2) "Anna"))) (set! (vec 1) '("Sue" "Sue")) (list (vec 2) (vec 1))) ⇒ ("Anna" ("Sue" "Sue"))
vector->list
vector
[start
[end
]]
The
vector->list
procedure returns a newly allocated list of the objects contained in the elements ofvector
betweenstart
andend
.(vector->list '#(dah dah didah)) ⇒ (dah dah didah) (vector->list '#(dah dah didah) 1 2) ⇒ (dah)
The
list->vector
procedure returns a newly created vector initialized to the elements of the listlist
, in order.(list->vector '(dididit dah)) ⇒ #(dididit dah)
vector->string
vector
[start
[end
]]
The
vector->string
procedure returns a newly allocated string of the objects contained in the elements ofvector
betweenstart
andend
. It is an error if any element ofvector
betweenstart
andend
is not a character, or is a character forbidden in strings.(vector->string #(#\1 #\2 #\3)) ⇒ "123" (vector->string #(#\1 #\2 #\3 #\4 #\5) 2 4) ⇒ "34"
string->vector
string
[start
[end
]]
The
string->vector
procedure returns a newly created vector initialized to the elements of the stringstring
betweenstart
andend
.(string->vector "ABC") ⇒ #(#\A #\B #\C) (string->vector "ABCDE" 1 3) ⇒ #(#\B #\C)
vector-copy
vector
[start
[end
]]
Returns a newly allocated copy of the elements of the given
vector
betweenstart
andend
. The elements of the new vector are the same (in the sense ofeqv?
) as the elements of the old.(define a #(1 8 2 8)) ; a may be immutable (define b (vector-copy a)) (vector-set! b 0 3) ; b is mutable b ⇒ #(3 8 2 8) (define c (vector-copy b 1 3)) c ⇒ #(8 2)
vector-copy!
to
at
from
[start
[end
]]
Copies the elements of vector from between start and end to vector to, starting at at. The order in which elements are copied is unspecified, except that if the source and destination overlap, copying takes place as if the source is first copied into a temporary vector and then into the destination. This can be achieved without allocating storage by making sure to copy in the correct direction in such circumstances.
It is an error if
at
is less than zero or greater than the length ofto
. It is also an error if(- (vector-length
is less thanto
)at
)(-
.end
start
)(define a (vector 1 2 3 4 5)) (define b (vector 10 20 30 40 50)) (vector-copy! b 1 a 0 2) b ⇒ #(10 1 2 40 50)
Creates a newly allocated vector whose elements are the concatenation of the elements of the given arguments. Each
arg
may be a vector or a list.(vector-append #(a b c) #(d e f)) ⇒ #(a b c d e f)
vector-fill!
vector fill
[start
[end
]]
Stores
fill
in in the elements ofvector
betweenstart
andend
.(define a (vector 1 2 3 4 5)) (vector-fill! a 'smash 2 4) a ⇒ #(1 2 smash smash 5)
vector-map
proc
vector
_1
vector
_2
…
The
vector
s must all have the same length.proc
should accept as many arguments as there arevector
s and return a single value.The
vector-map
procedure appliesproc
element–wise to the elements of thevector
s and returns a vector of the results, in order.proc
is always called in the same dynamic environment asvector-map
itself. The order in whichproc
is applied to the elements of thevector
s is unspecified. If multiple returns occur fromvector-map
, the return values returned by earlier returns are not mutated.Analogous to
map
.
vector-for-each
proc
vector
_1
vector
_2
…
The
vector
s must all have the same length.proc
should accept as many arguments as there arevector
s. Thevector-for-each
procedure appliesproc
element–wise to the elements of thevector
s for its side effects, in order from the first elements to the last.proc
is always called in the same dynamic environment asvector-for-each
itself. The return values ofvector-for-each
are unspecified.Analogous to
for-each
.
Uniform vectors are vectors whose elements are of the same numeric type.
The are defined by SRFI-4.
The type names (such as s8vector
) are a Kawa extension.
The type of uniform vectors where each element can contain a signed 8-bit integer. Represented using an array of
byte
.
The type of uniform vectors where each element can contain an unsigned 8-bit integer. Represented using an array of
<byte>
, but each element is treated as if unsigned.This type is a synonym for
bytevector
, which has extra functions.
The type of uniform vectors where each element can contain a signed 16-bit integer. Represented using an array of
short
.
The type of uniform vectors where each element can contain an unsigned 16-bit integer. Represented using an array of
short
, but each element is treated as if unsigned.
The type of uniform vectors where each element can contain a signed 32-bit integer. Represented using an array of
int
.
The type of uniform vectors where each element can contain an unsigned 32-bit integer. Represented using an array of
int
, but each element is treated as if unsigned.
The type of uniform vectors where each element can contain a signed 64-bit integer. Represented using an array of
long
.
The type of uniform vectors where each element can contain an unsigned 64-bit integer. Represented using an array of
long
, but each element is treated as if unsigned.
The type of uniform vectors where each element can contain a 32-bit floating-point real. Represented using an array of
float
.
The type of uniform vectors where each element can contain a 64-bit floating-point real. Represented using an array of
double
.
Return true iff
value
is a uniform vector of the specified type.
Create a new uniform vector of the specified type, having room for
n
elements. Initialize each element tovalue
if it is specified; zero otherwise.
Create a new uniform vector of the specified type, whose length is the number of
value
s specified, and initialize it using thosevalue
s.
Return the length (in number of elements) of the uniform vector
v
.
Return the element at index
i
of the uniform vectorv
.
Set the element at index
i
of uniform vectorv
to the valuex
, which must be a number coercible to the appropriate type.
Convert the uniform vetor
v
to a list containing the elments ofv
.
Create a uniform vector of the appropriate type, initializing it with the elements of the list
l
. The elements ofl
must be numbers coercible the new vector's element type.
Each uniform array type is implemented as an underlying Java array,
and a length field.
The underlying type is
byte[]
for u8vector
or s8vector
;
short[]
for u16vector
or u16vector
;
int[]
for u32vector
or s32vector
;
long[]
for u64vector
or s64vector
;
float[]
for f32vector
; and
double[]
for f32vector
.
The length field allows a uniform array to only use the
initial part of the underlying array. (This can be used
to support Common Lisp's fill pointer feature.)
This also allows resizing a uniform vector. There is no
Scheme function for this, but you can use the setSize
method:
(invoke some-vector 'setSize 200)
If you have a Java array, you can create a uniform vector sharing with the Java array:
(define arr :: byte[] ((primitive-array-new byte) 10)) (define vec :: u8vector (make u8vector arr))
At this point vec
uses arr
for its underlying storage,
so changes to one affect the other.
It vec
is re-sized so it needs a larger underlying array,
then it will no longer use arr
.
Bytevectors represent blocks of binary data. They are
fixed-length sequences of bytes, where a byte
is an exact
integer in the range [0, 255]. A bytevector is typically more
space-efficient than a vector containing the same values.
The length of a bytevector is the number of elements that it contains. This number is a non-negative integer that is fixed when the bytevector is created. The valid indexes of a bytevector are the exact non-negative integers less than the length of the bytevector, starting at index zero as with vectors.
The bytevector
type is equivalent to the u8vector
uniform vector type, but is specified
by the R7RS standard.
Bytevectors are written using the notation #u8(byte . . . )
.
For example, a bytevector of length 3 containing the byte
0 in element 0, the byte 10 in element 1, and the byte 5 in
element 2 can be written as following:
#u8(0 10 5)
Bytevector constants are self-evaluating, so they do not need to be quoted in programs.
Return a newly allocated bytevector whose elements contain the given arguments. Analogous to
vector
.(bytevector 1 3 5 1 3 5) ⇒ #u8(1 3 5 1 3 5) (bytevector) ⇒ #u8()
The
make-bytevector
procedure returns a newly allocated bytevector of lengthk
. Ifbyte
is given, then all elements of the bytevector are initialized tobyte
, otherwise the contents of each element are unspecified.(make-bytevector 2 12) ⇒ #u8(12 12)
bytevector-u8-ref
bytevector
k
It is an error if
k
is not a valid index ofbytevector
. Returns thek
th byte ofbytevector
.(bytevector-u8-ref ’#u8(1 1 2 3 5 8 13 21) 5) ⇒ 8
bytevector-u8-set!
bytevector
k
byte
It is an error if
k
is not a valid index ofbytevector
. Storesbyte
as thek
th byte ofbytevector
.(let ((bv (bytevector 1 2 3 4) (bytevector-u8-set! bv 1 3) bv) ⇒ #u8(1 3 3 4)
bytevector-copy
bytevector
[start
[end
]]
Returns a newly allocated bytevector containing the bytes in
bytevector
betweenstart
andend
.(define a #u8(1 2 3 4 5)) (bytevector-copy a 2 4)) ⇒ #u8(3 4)
bytevector-copy!
to
at
from
[start
[end
]]
Copies the bytes of bytevector
from
betweenstart
andend
to bytevectorto
, starting atat
. The order in which bytes are copied is unspecified, except that if the source and destination overlap, copying takes place as if the source is first copied into a temporary bytevector and then into the destination. This is achieved without allocating storage by making sure to copy in the correct direction in such circumstances.It is an error if
at
is less than zero or greater than the length ofto
. It is also an error if(- (bytevector-length
is less thanto
)at
)(-
.end
start
)(define a (bytevector 1 2 3 4 5)) (define b (bytevector 10 20 30 40 50)) (bytevector-copy! b 1 a 0 2) b ⇒ #u8(10 1 2 40 50)
bytevector-append
bytevector...
Returns a newly allocated bytevector whose elements are the concatenation of the elements in the given bytevectors.
(bytevector-append #u8(0 1 2) #u8(3 4 5)) ⇒ #u8(0 1 2 3 4 5)
Streams, sometimes called lazy lists, are a sequential data structure containing elements computed only on demand. A stream is either null or is a pair with a stream in its cdr. Since elements of a stream are computed only when accessed, streams can be infinite. Once computed, the value of a stream element is cached in case it is needed again.
Note: These are not the same as Java 8 streams.
(require 'srfi-41) (define fibs (stream-cons 1 (stream-cons 1 (stream-map + fibs (stream-cdr fibs))))) (stream->list 8 fibs) ⇒ (1 1 2 3 5 8 13 21)
See the SRFI 41 specification for details.
The Kawa implementations builds on promises.
The stream-null
value is a promise that evaluates to the empty list.
The result of stream-cons
is an eager immutable pair whose
car
and cdr
properties return promises.
Arrays are heterogeneous data structures whose elements are indexed by integer sequences of fixed length. The length of a valid index sequence is the rank or the number of dimensions of an array. The shape of an array consists of bounds for each index.
The lower bound b
and the upper bound e
of a dimension are
exact integers with (<=
. A valid index along the
dimension is an exact integer b
e
)k
that satisfies both
(<=
and b
k
)(<
.
The length of the array along the dimension is the difference
k
e
)(-
.
The size of an array is the product of the lengths of its dimensions.
e
b
)
A shape is specified as an even number of exact integers. These are alternately the lower and upper bounds for the dimensions of an array.
Returns a shape. The sequence
bound
... must consist of an even number of exact integers that are pairwise not decreasing. Each pair gives the lower and upper bound of a dimension. If the shape is used to specify the dimensions of an array andbound
... is the sequenceb0
e0
...bk
ek
... ofn
pairs of bounds, then a valid index to the array is any sequencej0
...jk
... ofn
exact integers where eachjk
satisfies(<=
andbk
jk
)(<
.jk
ek
)The shape of a
d
-dimensional array is ad
* 2 array where the element atk 0
contains the lower bound for an index along dimensionk
and the element atk 1
contains the corresponding upper bound, wherek
satisfies(<= 0
andk
)(<
.k
d
)
Returns a newly allocated array whose shape is given by
shape
. Ifobj
is provided, then each element is initialized to it. Otherwise the initial contents of each element is unspecified. The array does not retain a reference toshape
.
Returns a new array whose shape is given by
shape
and the initial contents of the elements areobj
... in row major order. The array does not retain a reference toshape
.
Returns the number of dimensions of
array
.(array-rank (make-array (shape 1 2 3 4)))Returns 2.
Returns the contents of the element of
array
at indexk
.... The sequencek
... must be a valid index toarray
. In the second form,index
must be either a vector or a 0-based 1-dimensional array containingk
....(array-ref (array (shape 0 2 0 3) 'uno 'dos 'tres 'cuatro 'cinco 'seis) 1 0)Returns
cuatro
.(let ((a (array (shape 4 7 1 2) 3 1 4))) (list (array-ref a 4 1) (array-ref a (vector 5 1)) (array-ref a (array (shape 0 2) 6 1))))Returns
(3 1 4)
.
Stores
obj
in the element ofarray
at indexk
.... Returns the void value. The sequencek
... must be a valid index toarray
. In the second form,index
must be either a vector or a 0-based 1-dimensional array containingk
....(let ((a (make-array (shape 4 5 4 5 4 5)))) (array-set! a 4 4 4 "huuhkaja") (array-ref a 4 4 4))Returns
"huuhkaja"
.
Returns a new array of
shape
shape that shares elements ofarray
throughproc
. The procedureproc
must implement an affine function that returns indices ofarray
when given indices of the array returned byshare-array
. The array does not retain a reference toshape
.(define i_4 (let* ((i (make-array (shape 0 4 0 4) 0)) (d (share-array i (shape 0 4) (lambda (k) (values k k))))) (do ((k 0 (+ k 1))) ((= k 4)) (array-set! d k 1)) i))Note: the affinity requirement for
proc
means that each value must be a sum of multiples of the arguments passed toproc
, plus a constant.Implementation note: arrays have to maintain an internal index mapping from indices
k1
...kd
to a single index into a backing vector; the composition of this mapping andproc
can be recognised as(
by setting each index in turn to 1 and others to 0, and all to 0 for the constant term; the composition can then be compiled away, together with any complexity that the user introduced in their procedure.+ n0
(*n1
k1
) ... (*nd
kd
))
Multi-dimensional arrays are specified
by SRFI-25.
In Kawa, a one-dimensional array whose lower bound is 0 is also a sequence.
Furthermore, if such an array is simple (not created share-array
)
it will be implemented using a <vector>
.
Uniform vectors and strings are also arrays in Kawa.
For example:
(share-array (f64vector 1.0 2.0 3.0 4.0 5.0 6.0) (shape 0 2 0 3) (lambda (i j) (+ (* 2 i) j)))
evaluates to a two-dimensionsal array of <double>
:
#2a((1.0 2.0 3.0) (3.0 4.0 5.0))
A hashtable is a data structure that associates keys with values. The hashtable has no intrinsic order for the (key, value) associations it contains, and supports in-place modification as the primary means of setting the contents of a hash table. Any object can be used as a key, provided a hash function and a suitable equivalence function is available. A hash function is a procedure that maps keys to exact integer objects.
The hashtable provides key lookup and destructive update in amortised
constant time, provided that a good hash function is used.
A hash function h
is acceptable for an equivalence predicate e
iff
(
implies
e
obj1
obj2
)(= (
.
A hash function h
obj1
) (h
obj2
))h
is good for a equivalence predicate e
if
it distributes the resulting hash values for non-equal objects
(by e
) as uniformly as possible over the range of hash
values, especially in the case when some (non-equal) objects resemble
each other by e.g. having common subsequences. This definition is
vague but should be enough to assert that e.g. a constant function is
not a good hash function.
Kawa provides two complete sets of functions for hashtables:
The functions specified by R6RS have names starting with
hashtable-
The functions specified by the older SRFI-69 specifiation have names starting with
hash-table-
Both interfaces use the same underlying datatype, so it is possible
to mix and match from both sets.
That datatype implements java.util.Map
.
Freshly-written code should probably use the R6RS functions.
To use these hash table functions in your Kawa program you must first:
(import (rnrs hashtables))
This section uses the hashtable
parameter name for arguments that
must be hashtables, and the key
parameter name for arguments that
must be hashtable keys.
Return a newly allocated mutable hashtable that accepts arbitrary objects as keys, and compares those keys with
eq?
. If an argument is given, the initial capacity of the hashtable is set to approximatelyk
elements.
Return a newly allocated mutable hashtable that accepts arbitrary objects as keys, and compares those keys with
eqv?
. If an argument is given, the initial capacity of the hashtable is set to approximatelyk
elements.
make-hashtable
hash-function
equiv
make-hashtable
hash-function
equiv
k
hash-function
andequiv
must be procedures.hash-function
should accept a key as an argument and should return a non–negative exact integer object.equiv
should accept two keys as arguments and return a single value. Neither procedure should mutate the hashtable returned bymake-hashtable
.The
make-hashtable
procedure returns a newly allocated mutable hashtable usinghash-function
as the hash function andequiv
as the equivalence function used to compare keys. If a third argument is given, the initial capacity of the hashtable is set to approximatelyk
elements.Both
hash-function
andequiv
should behave like pure functions on the domain of keys. For example, thestring-hash
andstring=?
procedures are permissible only if all keys are strings and the contents of those strings are never changed so long as any of them continues to serve as a key in the hashtable. Furthermore, any pair of keys for whichequiv
returns true should be hashed to the same exact integer objects byhash-function
.Note: Hashtables are allowed to cache the results of calling the hash function and equivalence function, so programs cannot rely on the hash function being called for every lookup or update. Furthermore any hashtable operation may call the hash function more than once.
Return the number of keys contained in
hashtable
as an exact integer object.
hashtable-ref
hashtable
key
default
Return the value in
hashtable
associated withkey
. Ifhashtable
does not contain an association forkey
,default
is returned.
hashtable-set!
hashtable
key
obj
Change
hashtable
to associatekey
withobj
, adding a new association or replacing any existing association forkey
, and returns unspecified values.
hashtable-delete!
hashtable
key
Remove any association for
key
withinhashtable
and returns unspecified values.
hashtable-contains?
hashtable
key
Return
#t
ifhashtable
contains an association forkey
,#f
otherwise.
hashtable-update!
hashtable
key
proc
default
proc
should accept one argument, should return a single value, and should not mutatehashtable
.The
hashtable-update!
procedure appliesproc
to the value inhashtable
associated withkey
, or todefault
ifhashtable
does not contain an association forkey
. Thehashtable
is then changed to associatekey
with the value returned byproc
.The behavior of
hashtable-update!
is equivalent to the following code, but is may be (and is in Kawa) implemented more efficiently in cases where the implementation can avoid multiple lookups of the same key:(hashtable-set! hashtable key (proc (hashtable-ref hashtable key default)))
hashtable-copy
hashtable
mutable
Return a copy of
hashtable
. If themutable
argument is provided and is true, the returned hashtable is mutable; otherwise it is immutable.
Remove all associations from
hashtable
and returns unspecified values.If a second argument is given, the current capacity of the hashtable is reset to approximately
k
elements.
Return a vector of all keys in
hashtable
. The order of the vector is unspecified.
Return two values, a vector of the keys in
hashtable
, and a vector of the corresponding values.Example:
(let ((h (make-eqv-hashtable))) (hashtable-set! h 1 'one) (hashtable-set! h 2 'two) (hashtable-set! h 3 'three) (hashtable-entries h)) ⇒ #(1 2 3) #(one two three) ; two return valuesthe order of the entries in the result vectors is not known.
hashtable-equivalence-function
hashtable
Return the equivalence function used by
hashtable
to compare keys. For hashtables created withmake-eq-hashtable
andmake-eqv-hashtable
, returnseq?
andeqv?
respectively.
The equal-hash
, string-hash
, and string-ci-hash
procedures of this section are acceptable as the hash functions of a
hashtable only if the keys on which they are called are not mutated
while they remain in use as keys in the hashtable.
Return an integer hash value for
obj
, based on its structure and current contents. This hash function is suitable for use withequal?
as an equivalence function.Note: Like
equal?
, theequal-hash
procedure must always terminate, even if its arguments contain cycles.
Return an integer hash value for
string
, based on its current contents. This hash function is suitable for use withstring=?
as an equivalence function.
Return an integer hash value for
string
based on its current contents, ignoring case. This hash function is suitable for use withstring-ci=?
as an equivalence function.
To use these hash table functions in your Kawa program you must first:
(require 'srfi-69)
or
(require 'hash-table)
or
(import (srfi :69 basic-hash-tables))
make-hash-table
[ equal?
[ hash
[ size-hint
]]] →
hash-table
Create a new hash table with no associations. The
equal?
parameter is a predicate that should accept two keys and return a boolean telling whether they denote the same key value; it defaults to theequal?
function.The
hash
parameter is a hash function, and defaults to an appropriate hash function for the givenequal?
predicate (see the Hashing section). However, an acceptable default is not guaranteed to be given for any equivalence predicate coarser thanequal?
, except forstring-ci=?
. (The functionhash
is acceptable forequal?
, so if you use coarser equivalence thanequal?
other thanstring-ci=?
, you must always provide the function hash yourself.) (An equivalence predicatec1
is coarser than a equivalence predicatec2
iff there exist valuesx
andy
such that(and (
.)c1
x
y
) (not (c2
x
y
)))The
size-hint
parameter can be used to suggested an approriate initial size. This option is not part of the SRFI-69 specification (though it is handled by the reference implementation), so specifying that option might be unportable.
alist->hash-table
alist
[ equal?
[ hash
[ size-hint
]]] →
hash-table
Takes an association list
alist
and creates a hash tablehash-table
which maps thecar
of every element inalist
to thecdr
of corresponding elements inalist
. Theequal?
,hash
, andsize-hint
parameters are interpreted as inmake-hash-table
. If some key occurs multiple times inalist
, the value in the first association will take precedence over later ones. (Note: the choice of usingcdr
(instead ofcadr
) for values tries to strike balance between the two approaches: usingcadr
would render this procedure unusable forcdr
alists, but not vice versa.)
hash-table-ref
hash-table
key
[ thunk
] →
value
This procedure returns the value associated to
key
inhash-table
. If no value is associated tokey
andthunk
is given, it is called with no arguments and its value is returned; ifthunk
is not given, an error is signalled. Given a good hash function, this operation should have an (amortised) complexity of O(1) with respect to the number of associations inhash-table
.
hash-table-ref/default
hash-table
key
default
→
value
Evaluates to the same value as
(hash-table-ref
. Given a good hash function, this operation should have an (amortised) complexity of O(1) with respect to the number of associations in hash-table.hash-table
key
(lambda ()default
))
hash-table-set!
hash-table
key
value
→
void
This procedure sets the value associated to
key
inhash-table
. The previous association (if any) is removed. Given a good hash function, this operation should have an (amortised) complexity of O(1) with respect to the number of associations in hash-table.
hash-table-delete!
hash-table
key
→
void
This procedure removes any association to
key
inhash-table
. It is not an error if no association for thekey
exists; in this case, nothing is done. Given a good hash function, this operation should have an (amortised) complexity of O(1) with respect to the number of associations in hash-table.
hash-table-exists?
hash-table
key
→
boolean
This predicate tells whether there is any association to
key
inhash-table
. Given a good hash function, this operation should have an (amortised) complexity of O(1) with respect to the number of associations in hash-table.
hash-table-size
hash-table
→
integer
Returns the number of associations in
hash-table
. This operation takes constant time.
hash-table-keys
hash-table
→
list
Returns a list of keys in
hash-table
. The order of the keys is unspecified.
hash-table-values
hash-table
→
list
Returns a list of values in
hash-table
. The order of the values is unspecified, and is not guaranteed to match the order of keys in the result ofhash-table-keys
.
hash-table-walk
hash-table
proc
→
void
proc
should be a function taking two arguments, a key and a value. This procedure callsproc
for each association inhash-table
, giving the key of the association as key and the value of the association as value. The results ofproc
are discarded. The order in whichproc
is called for the different associations is unspecified.
hash-table-fold
hash-table
f
init-value
→
final-value
This procedure calls
f
for every association inhash-table
with three arguments: the key of the association key, the value of the association value, and an accumulated value,val
. Theval
isinit-value
for the first invocation off
, and for subsequent invocations off
, the return value of the previous invocation off
. The valuefinal-value
returned byhash-table-fold
is the return value of the last invocation off
. The order in whichf
is called for different associations is unspecified.
hash-table->alist
hash-table
→
alist
Returns an association list such that the
car
of each element inalist
is a key inhash-table
and the correspondingcdr
of each element inalist
is the value associated to the key inhash-table
. The order of the elements is unspecified.The following should always produce a hash table with the same mappings as a hash table
h
:(alist->hash-table (hash-table->alisth
) (hash-table-equivalence-functionh
) (hash-table-hash-functionh
))
The Kawa implementation always calls these hash functions with a single
parameter, and expects the result to be within the entire
(32-bit signed) int
range, for compatibility with
standard hashCode
methods.
hash
object
[ bound
] →
integer
Produces a hash value for object in the range from 0 (inclusive) tp to
bound
(exclusive).If
bound
is not given, the Kawa implementation returns a value within the range(- (expt 2 32))
(inclusive) to(- (expt 2 32) 1)
(inclusive). It does this by calling the standardhashCode
method, and returning the result as is. (If theobject
is the Javanull
value, 0 is returned.) This hash function is acceptable forequal?
.
string-hash
string
[ bound
] →
integer
The same as
hash
, except that the argument string must be a string. (The Kawa implementation returns the same as thehash
function.)