mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-19 13:49:17 +02:00
178 lines
4.9 KiB
Scheme
178 lines
4.9 KiB
Scheme
|
|
(define (opt-hash eq-fn o)
|
|
(if (pair? o)
|
|
(car o)
|
|
(if (eq? eq? eq-fn) hash-by-identity hash)))
|
|
|
|
(define (make-hash-table x . o)
|
|
(if (comparator? x)
|
|
(%make-hash-table (comparator-equality-predicate x)
|
|
(comparator-hash-function x))
|
|
(%make-hash-table x (opt-hash x o))))
|
|
|
|
(define (hash-table comparator . o)
|
|
(let ((ht (make-hash-table comparator)))
|
|
(let lp ((ls o))
|
|
(when (pair? ls)
|
|
(hash-table-set! ht (car ls) (cadr ls))
|
|
(lp (cddr ls))))
|
|
ht))
|
|
|
|
(define (hash-table-copy ht . o)
|
|
(cond
|
|
((and (pair? o) (car o))
|
|
(%hash-table-copy ht))
|
|
((hash-table-mutable? ht)
|
|
(let ((res (%hash-table-copy ht)))
|
|
(make-immutable! res)
|
|
res))
|
|
(else
|
|
ht)))
|
|
|
|
(define (hash-table-set! ht . o)
|
|
(let lp ((ls o))
|
|
(when (pair? ls)
|
|
(%hash-table-set! ht (car ls) (cadr ls))
|
|
(lp (cddr ls)))))
|
|
|
|
(define (hash-table-fold a b c)
|
|
(if (hash-table? a)
|
|
(%hash-table-fold a b c)
|
|
(%hash-table-fold c a b)))
|
|
|
|
(define (hash-table-unfold stop? mapper successor seed comparator . o)
|
|
(let ((ht (make-hash-table comparator)))
|
|
(let lp ((acc seed))
|
|
(if (stop? acc)
|
|
ht
|
|
(call-with-values (lambda () (mapper acc))
|
|
(lambda (key value)
|
|
(hash-table-set! ht key value)
|
|
(lp (successor acc))))))))
|
|
|
|
(define (alist->hash-table alist x . o)
|
|
(if (comparator? x)
|
|
(%alist->hash-table alist
|
|
(comparator-equality-predicate x)
|
|
(comparator-hash-function x))
|
|
(%alist->hash-table alist x (opt-hash x o))))
|
|
|
|
(define hash-table-contains? hash-table-exists?)
|
|
|
|
(define (hash-table-empty? ht)
|
|
(zero? (hash-table-size ht)))
|
|
|
|
(define (hash-table-mutable? ht)
|
|
(not (immutable? ht)))
|
|
|
|
(define missing-key (list 'missing-key))
|
|
|
|
(define (hash-table=? value-cmp ht1 ht2)
|
|
(and (= (hash-table-size ht1)
|
|
(hash-table-size ht2))
|
|
(let lp ((ls (hash-table-keys ht1)))
|
|
(or (null? ls)
|
|
(let ((v1 (hash-table-ref/default ht1 (car ls) missing-key))
|
|
(v2 (hash-table-ref/default ht2 (car ls) missing-key)))
|
|
(and (not (eq? missing-key v1))
|
|
(not (eq? missing-key v2))
|
|
((comparator-equality-predicate value-cmp) v1 v2)
|
|
(lp (cdr ls))))))))
|
|
|
|
(define (hash-table-intern! ht key failure)
|
|
(hash-table-ref ht key (lambda ()
|
|
(let ((res (failure)))
|
|
(hash-table-set! ht key res)
|
|
res))))
|
|
|
|
(define (hash-table-delete! ht . keys)
|
|
(for-each (lambda (key) (%hash-table-delete! ht key)) keys))
|
|
|
|
(define (hash-table-pop! ht)
|
|
(let* ((key (car (hash-table-keys ht)))
|
|
(value (hash-table-ref ht key)))
|
|
(hash-table-delete! ht key)
|
|
(values key value)))
|
|
|
|
(define (hash-table-clear! ht)
|
|
(for-each
|
|
(lambda (key) (hash-table-delete! ht key))
|
|
(hash-table-keys ht)))
|
|
|
|
(define (hash-table-entries ht)
|
|
(values (hash-table-keys ht) (hash-table-values ht)))
|
|
|
|
(define (hash-table-find proc ht failure)
|
|
(call-with-current-continuation
|
|
(lambda (return)
|
|
(hash-table-for-each
|
|
(lambda (key value)
|
|
(let ((res (proc key value)))
|
|
(if res (return res))))
|
|
ht)
|
|
(failure))))
|
|
|
|
(define (hash-table-count proc ht)
|
|
(let ((count 0))
|
|
(hash-table-for-each
|
|
(lambda (key value)
|
|
(if (proc key value)
|
|
(set! count (+ count 1))))
|
|
ht)
|
|
count))
|
|
|
|
(define (hash-table-map proc cmp ht)
|
|
(let ((ht2 (make-hash-table cmp)))
|
|
(hash-table-for-each
|
|
(lambda (key value) (hash-table-set! ht2 key (proc value)))
|
|
ht)
|
|
ht2))
|
|
|
|
(define (hash-table-map! proc ht)
|
|
(for-each
|
|
(lambda (key value) (hash-table-set! ht key (proc key value)))
|
|
(hash-table-keys ht)
|
|
(hash-table-values ht)))
|
|
|
|
(define (hash-table-for-each proc ht)
|
|
(hash-table-walk ht proc))
|
|
|
|
(define (hash-table-map->list proc ht)
|
|
(map (lambda (cell) (proc (car cell) (cdr cell))) (hash-table->alist ht)))
|
|
|
|
(define (hash-table-prune! proc ht)
|
|
(for-each
|
|
(lambda (key value)
|
|
(if (proc key value)
|
|
(hash-table-delete! ht key)))
|
|
(hash-table-keys ht)
|
|
(hash-table-values ht)))
|
|
|
|
(define (hash-table-empty-copy ht)
|
|
(make-hash-table (hash-table-equivalence-function ht)
|
|
(hash-table-hash-function ht)))
|
|
|
|
(define hash-table-union! hash-table-merge!)
|
|
|
|
(define (hash-table-intersection! ht1 ht2)
|
|
(for-each
|
|
(lambda (key)
|
|
(if (not (hash-table-contains? ht2 key))
|
|
(hash-table-delete! ht1 key)))
|
|
(hash-table-keys ht1))
|
|
ht1)
|
|
|
|
(define (hash-table-difference! ht1 ht2)
|
|
(for-each
|
|
(lambda (key)
|
|
(if (hash-table-contains? ht2 key)
|
|
(hash-table-delete! ht1 key)))
|
|
(hash-table-keys ht1))
|
|
ht1)
|
|
|
|
(define (hash-table-xor! ht1 ht2)
|
|
(let* ((tmp (hash-table-copy ht1 #t))
|
|
(intersection (hash-table-intersection! tmp ht2)))
|
|
(hash-table-difference! (hash-table-union! ht1 ht2)
|
|
intersection)
|
|
ht1))
|