-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsrfi-69.scm
92 lines (76 loc) · 2.3 KB
/
srfi-69.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
;;; -*- Mode: Scheme; scheme48-package: srfi-69 -*-
;;;
;;; SRFI 69: Basic hash tables
;;;
(define* (make-hash-table (equal? equal?) (hash hash))
((make-table-maker equal? hash)))
(define (hash-table? t) (table? t))
(define* (alist->hash-table alist (equal? equal?) (hash hash))
(let ((table (make-hash-table equal? hash)))
(for-each (lambda (x) (hash-table-set! table (car x) (cdr x)))
alist)
table))
(define (hash-table-ref table key . thunk)
(let ((value (table-ref table key)))
(if (eq? value #f)
(if (null? thunk) (error "key not found") ((car thunk)))
value)))
(define (hash-table-ref/default table key default)
(hash-table-ref table key (lambda () default)))
(define (hash-table-set! table key value)
(table-set! table key value))
(define (hash-table-delete! table key)
(table-set! table key #f))
(define (hash-table-exists? table key)
(hash-table-ref table key (lambda () #f)))
(define (hash-table-size table)
(let ((size 0))
(table-walk
(lambda (k v) (set! size (+ size 1)))
table)
size))
(define (hash-table-keys table)
(let ((keys '()))
(table-walk
(lambda (k v) (set! keys (cons k keys)))
table)
keys))
(define (hash-table-values table)
(let ((values '()))
(table-walk
(lambda (k v) (set! values (cons v values)))
table)
values))
(define (hash-table-walk table proc)
(table-walk proc table))
(define (hash-table->alist table)
(let ((alist '()))
(table-walk
(lambda (k v) (set! alist (cons (list k v) alist)))
table)
alist))
(define (hash-table-copy table)
(let ((copy (make-hash-table)))
(table-walk
(lambda (k v) (hash-table-set! copy k v))
table)
copy))
; according to srfi-69 "hash function is acceptable for equal?"
(define (hash obj . rest)
(if (not (null? rest))
(let ((bound (car rest)))
(if (and (integer? bound) (> bound 0))
(let ((h (hash obj)))
(if (> h bound)
(remainder h bound)
h))
(error "invalid argument"
'(not (> integer 0))
`(while calling ,hash)
`(received ,bound))))
(cond
((pair? obj) (+ (hash (car obj))
(* 3 (hash (cdr obj)))))
((vector? obj) (hash (vector->list obj))) ; lazy mofo
((string? obj) (string-hash obj))
(else (default-hash-function obj)))))