Hash Tables (SRFI-69)¶
Hash tables provide efficient key-value storage with average O(1) lookup.
Import with (import (srfi 69)).
SRFI-69 tables iterate in no particular order. When iteration, folding,
or conversion must follow first-insertion order, use the portable
SRFI 250 (insertion-ordered hash tables) instead —
(import (srfi 250)); see SRFI Support.
Performance characteristics¶
| Operation | Average | Worst case |
|---|---|---|
hash-table-ref |
O(1) | O(n) |
hash-table-set! |
O(1) | O(n) |
hash-table-delete! |
O(1) | O(n) |
hash-table-size |
O(1) | O(1) |
hash-table->alist |
O(n) | O(n) |
hash-table-keys |
O(n) | O(n) |
Kaappi uses open-addressing with linear probing. The table resizes automatically when the load factor exceeds a threshold.
When to use hash tables vs. alists:
- Use hash tables when you have more than ~10 key-value pairs or when
lookup performance matters —
hash-table-refis O(1) vs.assocO(n) - Use alists for small, short-lived mappings or when you need the data as a list (e.g., JSON serialization)
- Hash tables are mutable; alists are persistent (the original is unchanged
when you
consa new pair onto the front)
Construction¶
make-hash-table¶
Syntax: (make-hash-table) | (make-hash-table equal-proc) | (make-hash-table equal-proc hash-proc)
Returns a newly allocated empty hash table. The optional equal-proc
specifies the equality predicate used to compare keys (default is
equal?). The optional hash-proc specifies the hash function used
to compute bucket indices; it must be consistent with the equality
predicate. When using eq? or eqv? as the equality predicate,
provide a matching hash function for correct behavior.
kaappi> (define ht (make-hash-table))
kaappi> (hash-table? ht)
;=> #t
kaappi> (hash-table-size ht)
;=> 0
kaappi> (define ht2 (make-hash-table string=? string-hash))
kaappi> (hash-table-set! ht2 "key" 42)
kaappi> (hash-table-ref ht2 "key")
;=> 42
See also: hash-table?,
alist->hash-table
alist->hash-table¶
Syntax: (alist->hash-table alist) | (alist->hash-table alist equal-proc) | (alist->hash-table alist equal-proc hash-proc)
Creates a new hash table and populates it from the association list
alist. Each element of alist should be a pair (key . value). If
alist contains duplicate keys, the first occurrence takes precedence.
The optional equal-proc and hash-proc arguments work as in
make-hash-table.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (hash-table-ref ht 'a)
;=> 1
kaappi> (hash-table-ref ht 'c)
;=> 3
kaappi> (hash-table-size ht)
;=> 3
kaappi> (alist->hash-table '((x . 10) (x . 20)))
kaappi> (hash-table-ref (alist->hash-table '((x . 10) (x . 20))) 'x)
;=> 10
See also: hash-table->alist,
make-hash-table
hash-table-copy¶
Syntax: (hash-table-copy ht)
Returns a shallow copy of hash table ht. The new table has the same equality and hash procedures, and contains the same key-value associations. Mutating the copy does not affect the original, and vice versa. Values are not recursively copied -- the copy shares the same value objects.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2))))
kaappi> (define ht2 (hash-table-copy ht))
kaappi> (hash-table-set! ht2 'a 99)
kaappi> (hash-table-ref ht 'a)
;=> 1
kaappi> (hash-table-ref ht2 'a)
;=> 99
See also: make-hash-table,
hash-table->alist
Type Predicate¶
hash-table?¶
Syntax: (hash-table? obj)
Returns #t if obj is a hash table, #f otherwise.
kaappi> (hash-table? (make-hash-table))
;=> #t
kaappi> (hash-table? '((a . 1) (b . 2)))
;=> #f
kaappi> (hash-table? '#(1 2 3))
;=> #f
kaappi> (hash-table? "hello")
;=> #f
See also: make-hash-table,
hash-table?
Lookup and Mutation¶
hash-table-ref¶
Syntax: (hash-table-ref ht key) | (hash-table-ref ht key failure-thunk)
Returns the value associated with key in hash table ht. O(1) average.
If key is not found and a failure-thunk is provided, the thunk is
called with no arguments and its result is returned. If key is not
found and no thunk is provided, an error is raised. Keys are compared
using the hash table's equality predicate (equal? by default).
Errors: Raises an error if key is not found and no failure thunk
is provided. The optional third argument is a thunk that is called on a
miss — for a plain default value, use
hash-table-ref/default.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (hash-table-ref ht 'a)
;=> 1
kaappi> (hash-table-ref ht 'b)
;=> 2
kaappi> (hash-table-ref ht 'z (lambda () #f))
;=> #f
kaappi> (hash-table-ref/default ht 'z 0)
;=> 0
Common pattern — safe lookup with default:
See also: hash-table-exists?,
hash-table-set!
hash-table-ref/default¶
Syntax: (hash-table-ref/default ht key default)
Like hash-table-ref, but default is a plain
value (not a thunk) returned when key is not present.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2))))
kaappi> (hash-table-ref/default ht 'a 0)
;=> 1
kaappi> (hash-table-ref/default ht 'z 0)
;=> 0
See also: hash-table-ref,
hash-table-update!/default
hash-table-set!¶
Syntax: (hash-table-set! ht key value)
Associates key with value in hash table ht. If key already exists, its value is replaced. O(1) average. Returns void. The table resizes automatically when needed.
kaappi> (define ht (make-hash-table))
kaappi> (hash-table-set! ht 'x 10)
kaappi> (hash-table-set! ht 'y 20)
kaappi> (hash-table-ref ht 'x)
;=> 10
kaappi> (hash-table-set! ht 'x 99)
kaappi> (hash-table-ref ht 'x)
;=> 99
kaappi> (hash-table-size ht)
;=> 2
See also: hash-table-ref,
hash-table-delete!,
hash-table-update!/default
hash-table-delete!¶
Syntax: (hash-table-delete! ht key)
Removes the association for key from hash table ht. If key is not present, the table is unchanged. Returns void.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (hash-table-size ht)
;=> 3
kaappi> (hash-table-delete! ht 'b)
kaappi> (hash-table-size ht)
;=> 2
kaappi> (hash-table-exists? ht 'b)
;=> #f
kaappi> (hash-table-delete! ht 'z)
kaappi> (hash-table-size ht)
;=> 2
See also: hash-table-set!,
hash-table-exists?
hash-table-exists?¶
Syntax: (hash-table-exists? ht key)
Returns #t if key is associated with a value in hash table ht,
#f otherwise.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2))))
kaappi> (hash-table-exists? ht 'a)
;=> #t
kaappi> (hash-table-exists? ht 'z)
;=> #f
kaappi> (hash-table-delete! ht 'a)
kaappi> (hash-table-exists? ht 'a)
;=> #f
See also: hash-table-ref,
hash-table-size
hash-table-update!/default¶
Syntax: (hash-table-update!/default ht key proc default)
Updates the value associated with key in ht by applying proc to the current value. If key does not exist, proc is applied to default and the result is stored. This is equivalent to:
but may be implemented more efficiently.
kaappi> (define ht (make-hash-table))
kaappi> (hash-table-update!/default ht 'count (lambda (n) (+ n 1)) 0)
kaappi> (hash-table-ref ht 'count)
;=> 1
kaappi> (hash-table-update!/default ht 'count (lambda (n) (+ n 1)) 0)
kaappi> (hash-table-ref ht 'count)
;=> 2
kaappi> (define counts (make-hash-table))
kaappi> (for-each (lambda (word)
(hash-table-update!/default counts word
(lambda (n) (+ n 1)) 0))
'(the cat sat on the mat))
kaappi> (hash-table-ref counts 'the)
;=> 2
kaappi> (hash-table-ref counts 'cat)
;=> 1
See also: hash-table-set!,
hash-table-ref
Size and Inspection¶
hash-table-size¶
Syntax: (hash-table-size ht)
Returns the number of key-value associations in hash table ht.
kaappi> (hash-table-size (make-hash-table))
;=> 0
kaappi> (hash-table-size (alist->hash-table '((a . 1) (b . 2) (c . 3))))
;=> 3
See also: hash-table-keys,
hash-table-exists?
hash-table-keys¶
Syntax: (hash-table-keys ht)
Returns a list of all keys in hash table ht. The order of keys is unspecified.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (hash-table-keys ht)
;=> (b a c)
kaappi> (hash-table-keys (make-hash-table))
;=> ()
See also: hash-table-values,
hash-table-size
hash-table-values¶
Syntax: (hash-table-values ht)
Returns a list of all values in hash table ht. The order of values is
unspecified but corresponds to the order of hash-table-keys.
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (hash-table-values ht)
;=> (2 1 3)
kaappi> (hash-table-values (make-hash-table))
;=> ()
See also: hash-table-keys,
hash-table->alist
Iteration and Conversion¶
hash-table-walk¶
Syntax: (hash-table-walk ht proc)
Calls (proc key value) for each key-value association in hash table
ht. The order of iteration is unspecified. The return value is void.
It is an error to mutate ht during the walk (add or remove keys).
kaappi> (define ht (alist->hash-table '((a . 1) (b . 2) (c . 3))))
kaappi> (define sum 0)
kaappi> (hash-table-walk ht (lambda (k v) (set! sum (+ sum v))))
kaappi> sum
;=> 6
kaappi> (hash-table-walk ht
(lambda (k v) (display k) (display ": ") (display v) (newline)))
c: 3
a: 1
b: 2
Note
The output order above is illustrative. Hash table iteration order is not guaranteed and may differ between runs.
See also: hash-table-keys,
hash-table->alist,
for-each
hash-table->alist¶
Syntax: (hash-table->alist ht)
Returns an association list containing the key-value pairs of hash
table ht. Each element is a pair (key . value). The order of
elements is unspecified.
kaappi> (define ht (make-hash-table))
kaappi> (hash-table-set! ht 'x 10)
kaappi> (hash-table-set! ht 'y 20)
kaappi> (hash-table->alist ht)
;=> ((y . 20) (x . 10))
kaappi> (hash-table->alist (make-hash-table))
;=> ()
See also: alist->hash-table,
hash-table-keys,
hash-table-values
hash-table-equivalence-function¶
(hash-table-equivalence-function ht) → procedure
Returns the equivalence function used by the hash table. Kaappi hash
tables always use equal?.
hash-table-hash-function¶
(hash-table-hash-function ht) → procedure
Returns the hash function used by the hash table.