123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- ;;; Hash a string.
- (define (hash-string str size)
- (let ((len (string-length str)))
- (let loop ((i 0)
- (accum 0))
- (if (= i len)
- (modulo accum size)
- (loop (+ i 1)
- (modulo
- (+ (builtin char->integer (string-ref str i))
- (* 31 accum))
- size))))))
- ;;; Hash an object.
- (define (hash obj size)
- (cond ((number? obj) (modulo obj size))
- ((string? obj) (hash-string obj size))
- ((symbol? obj)
- (hash-string (symbol->string obj) size))
- ((char? obj)
- (hash-string (make-string 1 obj) size))
- ((boolean? obj)
- (modulo (if obj 2 1) size))
- ((pair? obj)
- (modulo
- (+ (hash (car obj) size)
- (hash (cdr obj) size))
- size))
- (else 0)))
- ;;; Hash table type tag.
- (define hash-table-tag (list 'hash-table))
- (define (tagged-vector? obj tag)
- (and (vector? obj)
- (> (vector-length obj) 0)
- (eq? (vector-ref obj 0) tag)))
- ;;; Return #t if obj is a hash table.
- (define (hash-table? obj)
- (tagged-vector? obj hash-table-tag))
- (define (make-hash-table-aux aproc)
- (lambda ()
- (let ((size 101))
- (vector hash-table-tag aproc
- (make-vector size '())))))
- ;;; Make a hash table using assoc.
- (define make-hash-table (make-hash-table-aux assoc))
- ;;; Make a hash table using assq.
- ;;; Get the associative list procedure
- ;;; from a hash table.
- (define (hash-table-aproc ht) (vector-ref ht 1))
- ;;; Get the vector from a hash table.
- (define (hash-table-vector ht) (vector-ref ht 2))
- (define (hash-table-using aproc)
- (lambda (obj)
- (and (hash-table? obj)
- (eq? (hash-table-aproc obj) aproc))))
- ;;; Set a value in a hash table.
- (define (hash-table-set! ht key val)
- (let ((vec (hash-table-vector ht)))
- (let ((hashval (hash key (vector-length vec))))
- (let ((alist (vector-ref vec hashval)))
- (let ((pair ((hash-table-aproc ht) key alist)))
- (if pair
- (set-cdr! pair val)
- (vector-set! vec hashval
- (cons (cons key val)
- alist))))))))
- ;;; Get a value from a hash table.
- (define (hash-table-ref ht key default)
- (let ((vec (hash-table-vector ht)))
- (let ((res ((hash-table-aproc ht)
- key
- (vector-ref vec (hash key (vector-length vec))))))
- (if res (cdr res) default))))
- (define (hash-table-pred ht)
- equal?)
- ;(let ((aproc (hash-table-aproc ht)))
- ;(cond ((eq? aproc assq) eq?)
- ; ((eq? aproc assv) eqv?)
- ; ((eq? aproc assoc) equal?))))
- ;;; Delete a key from a hash table.
- (define (hash-table-delete! ht key)
- (let ((pred? (hash-table-pred ht))
- (vec (hash-table-vector ht)))
- (let ((hashval (hash key (vector-length vec))))
- (let loop ((alist (vector-ref vec hashval))
- (accum '()))
- (cond ((null? alist)
- (vector-set! vec hashval accum))
- ((pred? (caar alist) key)
- (loop (cdr alist) accum))
- (else
- (loop (cdr alist)
- (cons (car alist) accum))))))))
- ;;; Convert an associative list to
- ;;; a hash table.
- (define (alist->hash-table-aux aproc)
- (lambda (alist)
- (let ((ht ((make-hash-table-aux aproc))))
- (for-each
- (lambda (pair)
- (hash-table-set! ht (car pair) (cdr pair)))
- alist)
- ht)))
- (define alist->hash-table (alist->hash-table-aux assoc))
- ;(define alist->hash-tableq (alist->hash-table-aux assq))
- ;(define alist->hash-tablev (alist->hash-table-aux assv))
- (define (every n lst)
- (cond ((null? lst) '())
- ((zero? n) (every (+ n 1) (cdr lst)))
- (else
- (cons (car lst)
- (every (- n 1) (cdr lst))))))
- (define (zip a b)
- (map cons a b))
- ;(define (hash-table . args)
- ; (alist->hash-table
- ; (zip (every 1 args) (every 0 args))))
- ;(define (hash-tableq . args)
- ; (alist->hash-tableq
- ; (zip (every 1 args) (every 0 args))))
- ;(define (hash-tablev . args)
- ; (alist->hash-tablev
- ; (zip (every 1 args) (every 0 args))))
- ;;; Convert a hash table to an
- ;;; associative list.
- (define (concatenate lol)
- (if (null? lol)
- '()
- (append (car lol) (concatenate (cdr lol)))))
- (define (hash-table->alist ht)
- (concatenate
- (vector->list (hash-table-vector ht))))
- ;;; Make a copy of an associative list.
- ;;; The new one is backwards, but that should
- ;;; not matter.
- (define (alist-copy alist)
- (let loop ((alist alist)
- (accum '()))
- (if (null? alist)
- accum
- (loop
- (cdr alist)
- (cons (cons (caar alist) (cdar alist)) accum)))))
- ;;; Make a copy of a hash table.
- (define (hash-table-copy ht)
- (let ((old-vec (hash-table-vector ht)))
- (let ((size (vector-length old-vec)))
- (let ((new-vec (make-vector size)))
- (let loop ((i 0))
- (if (= i size)
- (vector hash-table-tag (hash-table-aproc ht) new-vec)
- (begin
- (vector-set! new-vec i
- (alist-copy (vector-ref old-vec i)))
- (loop (+ i 1)))))))))
|