diff options
| author | 2021-10-16 11:27:30 +0300 | |
|---|---|---|
| committer | 2021-10-16 11:27:30 +0300 | |
| commit | 84463b24c49e8333b81567c5e0148b8f4bcd103f (patch) | |
| tree | 08dd6a3d5ac723e8f8fb8b11d6ee45fa575609b2 | |
| parent | merge (diff) | |
work
| -rw-r--r-- | srfi-225-test.scm | 466 | ||||
| -rw-r--r-- | srfi-225.html | 22 | ||||
| -rw-r--r-- | srfi/225.sld | 73 | ||||
| -rw-r--r-- | srfi/alist-impl.scm | 75 | ||||
| -rw-r--r-- | srfi/default-impl.scm | 373 | ||||
| -rw-r--r-- | srfi/externals.scm | 104 | ||||
| -rw-r--r-- | srfi/indexes.scm | 37 | ||||
| -rw-r--r-- | srfi/plist-impl.scm | 121 | ||||
| -rw-r--r-- | srfi/srfi-69-impl.scm | 57 |
9 files changed, 794 insertions, 534 deletions
diff --git a/srfi-225-test.scm b/srfi-225-test.scm index 746cfd5..cb09a22 100644 --- a/srfi-225-test.scm +++ b/srfi-225-test.scm @@ -3,17 +3,31 @@ (scheme write) (srfi 1) (prefix (srfi 69) t69-) - (prefix (srfi 125) t125-) - (prefix (srfi 126) t126-) + ;(prefix (srfi 125) t125-) + ;(prefix (srfi 126) t126-) (srfi 128) - (srfi 146) - (srfi 146 hash) + ;(srfi 146) + ;(srfi 146 hash) + (srfi 158) (srfi 225)) (cond-expand (chibi (import (rename (except (chibi test) test-equal) - (test test-equal)))) + (test test-equal) + (test-group test-group*))) + (define test-skip-count 0) + (define (test-skip n) + (set! test-skip-count n)) + (define-syntax test-group + (syntax-rules () + ((_ name body ...) + (test-group* + name + (if (> test-skip-count 0) + (set! test-skip-count (- test-skip-count 1)) + (let () + body ...))))))) (else (import (srfi 64)))) @@ -21,7 +35,7 @@ ;; which counts how often each dtd's method was called ;; verify that all functions were tested (define (wrap-dtd dtd) - (define proc-count (+ 1 dict-comparator-id)) + (define proc-count (+ 1 dict-adjoin-accumulator-id)) (define counter (make-vector proc-count 0)) (define wrapper-dtd-args (let loop ((indexes (iota proc-count)) @@ -40,27 +54,29 @@ (apply make-dtd wrapper-dtd-args) counter)) -(define (do-test real-dtd alist->dict comparator) +(define (test-for-each expect-success for-each-proc expected-keys) + (call/cc (lambda (cont) + (with-exception-handler + (lambda (err) + (unless expect-success + (cont #t))) + (lambda () + (define lst '()) + (for-each-proc + (lambda (key value) + (set! lst (append lst (list key))))) + (test-equal (length lst) (length expected-keys)) + (for-each + (lambda (key) + (test-assert (find (lambda (key*) (equal? key key*)) + expected-keys))) + lst)))))) + +(define (do-test real-dtd alist->dict comparator mutable?) (define-values (dtd counter) (wrap-dtd real-dtd)) - (test-group - "make-dictionary" - (define dict (make-dictionary dtd comparator)) - (test-assert (dictionary? dtd dict)) - (test-assert (dict-empty? dtd dict))) - - (test-group - "dict-unfold" - (define (stop? value) (> value 1)) - (define seed 0) - (define (mapper seed) (values (number->string seed) seed)) - (define (successor seed) (+ 1 seed)) - (define dict (dict-unfold dtd comparator stop? mapper successor seed)) - (test-equal 2 (dict-size dtd dict)) - (test-equal 0 (dict-ref dtd dict "0")) - (test-equal 1 (dict-ref dtd dict "1"))) (test-group "dictionary?" @@ -78,6 +94,19 @@ (test-assert (not (dict-contains? dtd (alist->dict '()) 'a))) (test-assert (not (dict-contains? dtd (alist->dict '((b . c))) 'a))) (test-assert (dict-contains? dtd (alist->dict '((a . b))) 'a))) + + (test-group + "dict=?" + (define dict1 (alist->dict '((a . 1) (b . 2)))) + (define dict2 (alist->dict '((b . 2) (a . 1)))) + (define dict3 (alist->dict '((a . 1)))) + (define dict4 (alist->dict '((a . 2) (b . 2)))) + + (test-assert (dict=? dtd = dict1 dict2)) + (test-assert (not (dict=? dtd = dict1 dict3))) + (test-assert (not (dict=? dtd = dict3 dict1))) + (test-assert (not (dict=? dtd = dict1 dict4))) + (test-assert (not (dict=? dtd = dict4 dict1)))) (test-group "dict-ref" @@ -88,7 +117,37 @@ "dict-ref/default" (test-equal (dict-ref/default dtd (alist->dict '((a . b))) 'a 'c) 'b) (test-equal (dict-ref/default dtd (alist->dict '((a* . b))) 'a 'c) 'c)) - + + (test-group + "dict-min-key" + (define dict (alist->dict '((2 . a) (1 . b) (3 . c)))) + (call/cc (lambda (cont) + (with-exception-handler + (lambda (err) + (unless (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (cont #t))) + (lambda () + (define key (dict-min-key dtd dict)) + (test-equal 1 key)))))) + + (test-group + "dict-max-key" + (define dict (alist->dict '((2 . a) (3 . b) (1 . c)))) + (call/cc (lambda (cont) + (with-exception-handler + (lambda (err) + (unless (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (cont #t))) + (lambda () + (define key (dict-max-key dtd dict)) + (test-equal 3 key)))))) + + (when mutable? + (test-skip 1)) (test-group "dict-set" (define dict-original (alist->dict '((a . b)))) @@ -98,12 +157,16 @@ (test-equal 'b (dict-ref dtd dict-original' a)) (test-equal #f (dict-ref/default dtd dict-original 'a2 #f))) + (unless mutable? + (test-skip 1)) (test-group "dict-set!" (define d (dict-set! dtd (alist->dict '((a . b))) 'a 'c 'a2 'b2)) (test-equal 'c (dict-ref dtd d 'a )) (test-equal 'b2 (dict-ref dtd d 'a2))) + (when mutable? + (test-skip 1)) (test-group "dict-adjoin" (define dict-original (alist->dict '((a . b)))) @@ -112,12 +175,16 @@ (test-equal 'b2 (dict-ref dtd d 'a2)) (test-equal #f (dict-ref/default dtd dict-original 'a2 #f))) + (unless mutable? + (test-skip 1)) (test-group "dict-adjoin!" (define d (dict-adjoin! dtd (alist->dict '((a . b))) 'a 'c 'a2 'b2)) (test-equal 'b (dict-ref dtd d 'a)) (test-equal 'b2 (dict-ref dtd d 'a2))) + (when mutable? + (test-skip 1)) (test-group "dict-delete" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -125,11 +192,15 @@ (test-equal (dict->alist dtd d) '((c . d))) (test-equal 'b (dict-ref dtd dict-original 'a))) + (unless mutable? + (test-skip 1)) (test-group "dict-delete!" (define d (dict-delete! dtd (alist->dict '((a . b) (c . d))) 'a 'b)) (test-equal (dict->alist dtd d) '((c . d)))) + (when mutable? + (test-skip 1)) (test-group "dict-delete-all" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -137,11 +208,15 @@ (test-equal (dict->alist dtd d) '((c . d))) (test-equal 'b (dict-ref dtd dict-original 'a))) + (unless mutable? + (test-skip 1)) (test-group "dict-delete-all!" (define d (dict-delete-all! dtd (alist->dict '((a . b) (c . d))) '(a b))) (test-equal (dict->alist dtd d) '((c . d)))) + (when mutable? + (test-skip 1)) (test-group "dict-replace" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -150,12 +225,16 @@ (test-equal 'd (dict-ref dtd d 'c)) (test-equal 'b (dict-ref dtd dict-original 'a))) + (unless mutable? + (test-skip 1)) (test-group "dict-replace!" (define d (dict-replace! dtd (alist->dict '((a . b) (c . d))) 'a 'b2)) (test-equal 'b2 (dict-ref dtd d 'a)) (test-equal 'd (dict-ref dtd d 'c))) + (when mutable? + (test-skip 1)) (test-group "dict-intern" ;; intern existing @@ -176,6 +255,8 @@ (test-equal 'd value) (test-equal #f (dict-ref/default dtd dict-original 'c #f)))) + (unless mutable? + (test-skip 1)) (test-group "dict-intern!" ;; intern existing @@ -194,6 +275,8 @@ (test-equal 'd (dict-ref dtd d 'c)) (test-equal 'd value))) + (when mutable? + (test-skip 1)) (test-group "dict-update" ;; update existing @@ -216,6 +299,8 @@ (test-equal "d12" (dict-ref dtd d 'c)) (test-equal #f (dict-ref/default dtd dict-original 'c #f)))) + (unless mutable? + (test-skip 1)) (test-group "dict-update!" ;; update existing @@ -235,6 +320,8 @@ (lambda (x) (string-append x "1")))) (test-equal "d12" (dict-ref dtd d 'c)))) + (when mutable? + (test-skip 1)) (test-group "dict-update/default" ;; update existing @@ -256,6 +343,8 @@ (test-equal "d12" (dict-ref dtd d 'c)) (test-equal #f (dict-ref/default dtd dict-original 'c #f)))) + (unless mutable? + (test-skip 1)) (test-group "dict-update/default!" ;; update existing @@ -274,6 +363,8 @@ "d1")) (test-equal "d12" (dict-ref dtd d 'c)))) + (when mutable? + (test-skip 1)) (test-group "dict-pop" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -292,6 +383,8 @@ (test-assert 'b (dict-ref dtd dict-original 'a)) (test-assert 'd (dict-ref dtd dict-original 'c))) + (unless mutable? + (test-skip 1)) (test-group "dict-pop!" (define-values @@ -307,6 +400,8 @@ (equal? key 'c) (equal? value 'd))))) + (when mutable? + (test-skip 1)) (test-group "dict-map" (define dict-original (alist->dict '((a . "a") (b . "b")))) @@ -319,6 +414,8 @@ (test-equal "a" (dict-ref dtd dict-original 'a)) (test-equal "b" (dict-ref dtd dict-original 'b))) + (unless mutable? + (test-skip 1)) (test-group "dict-map!" (define d (dict-map! dtd @@ -328,6 +425,8 @@ (test-equal "a2" (dict-ref dtd d 'a)) (test-equal "b2" (dict-ref dtd d 'b))) + (when mutable? + (test-skip 1)) (test-group "dict-filter" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -339,6 +438,8 @@ (test-equal '((a . b)) (dict->alist dtd d)) (test-equal 'd (dict-ref dtd dict-original 'c))) + (unless mutable? + (test-skip 1)) (test-group "dict-filter!" (define d (dict-filter! dtd @@ -347,6 +448,8 @@ (alist->dict '((a . b) (c . d))))) (test-equal '((a . b)) (dict->alist dtd d))) + (when mutable? + (test-skip 1)) (test-group "dict-remove" (define dict-original (alist->dict '((a . b) (c . d)))) @@ -357,6 +460,8 @@ (test-equal '((c . d)) (dict->alist dtd d)) (test-equal 'd (dict-ref dtd dict-original 'c))) + (unless mutable? + (test-skip 1)) (test-group "dict-remove!" (define d (dict-remove! dtd @@ -365,122 +470,94 @@ (alist->dict '((a . b) (c . d))))) (test-equal '((c . d)) (dict->alist dtd d))) + (when mutable? + (test-skip 1)) (test-group - "dict-search" + "dict-alter" ;; ignore (let () - (define-values - (dict value) - (dict-search dtd (alist->dict '((a . b))) 'c - (lambda (insert ignore) - (ignore 'foo)) - (lambda args - (error "shouldn't happen")))) - (test-equal '((a . b)) (dict->alist dtd dict)) - (test-equal value 'foo)) + (define dict (dict-alter dtd (alist->dict '((a . b))) 'c + (lambda (insert ignore) + (ignore)) + (lambda args + (error "shouldn't happen")))) + (test-equal '((a . b)) (dict->alist dtd dict))) ;; insert (let () (define dict-original (alist->dict '((a . b)))) - (define-values - (dict value) - (dict-search dtd dict-original 'c + (define dict (dict-alter dtd dict-original 'c (lambda (insert ignore) - (insert 'd 'foo)) + (insert 'd)) (lambda args (error "shouldn't happen")))) (test-equal 'b (dict-ref dtd dict 'a)) (test-equal 'd (dict-ref dtd dict 'c)) - (test-equal value 'foo) (test-equal #f (dict-ref/default dtd dict-original 'c #f))) ;; update (let () (define dict-original (alist->dict '((a . b)))) - (define-values - (dict value) - (dict-search dtd dict-original 'a - (lambda args - (error "shouldn't happen")) - (lambda (key value update delete) - (update 'a2 'b2 'foo)))) + (define dict (dict-alter dtd dict-original 'a + (lambda args + (error "shouldn't happen")) + (lambda (key value update delete) + (update 'a2 'b2)))) (test-equal '((a2 . b2)) (dict->alist dtd dict)) - (test-equal value 'foo) (test-equal #f (dict-ref/default dtd dict-original 'a2 #f)) (test-equal 'b (dict-ref dtd dict-original 'a))) ;; delete (let () (define dict-original (alist->dict '((a . b) (c . d)))) - (define-values - (dict value) - (dict-search dtd dict-original 'a - (lambda args - (error "shouldn't happen")) - (lambda (key value update delete) - (delete 'foo)))) + (define dict (dict-alter dtd dict-original 'a + (lambda args + (error "shouldn't happen")) + (lambda (key value update delete) + (delete)))) (test-equal '((c . d)) (dict->alist dtd dict)) - (test-equal value 'foo) (test-equal 'b (dict-ref dtd dict-original 'a)))) + (unless mutable? + (test-skip 1)) (test-group - "dict-search!" + "dict-alter!" ;; ignore (let () - (define-values - (dict value) - (dict-search! dtd (alist->dict '((a . b))) 'c - (lambda (insert ignore) - (ignore 'foo)) - (lambda args - (error "shouldn't happen")))) - (test-equal '((a . b)) (dict->alist dtd dict)) - (test-equal value 'foo)) + (define dict (dict-alter! dtd (alist->dict '((a . b))) 'c + (lambda (insert ignore) + (ignore)) + (lambda args + (error "shouldn't happen")))) + (test-equal '((a . b)) (dict->alist dtd dict))) ;; insert (let () - (define-values - (dict value) - (dict-search! dtd (alist->dict '((a . b))) 'c - (lambda (insert ignore) - (insert 'd 'foo)) - (lambda args - (error "shouldn't happen")))) + (define dict (dict-alter! dtd (alist->dict '((a . b))) 'c + (lambda (insert ignore) + (insert 'd)) + (lambda args + (error "shouldn't happen")))) (test-equal 'b (dict-ref dtd dict 'a)) - (test-equal 'd (dict-ref dtd dict 'c)) - (test-equal value 'foo)) + (test-equal 'd (dict-ref dtd dict 'c))) ;; update (let () - (define-values - (dict value) - (dict-search! dtd (alist->dict '((a . b))) 'a - (lambda args - (error "shouldn't happen")) - (lambda (key value update delete) - (update 'a2 'b2 'foo)))) - (test-equal '((a2 . b2)) (dict->alist dtd dict)) - (test-equal value 'foo)) + (define dict (dict-alter! dtd (alist->dict '((a . b))) 'a + (lambda args + (error "shouldn't happen")) + (lambda (key value update delete) + (update 'a2 'b2)))) + (test-equal '((a2 . b2)) (dict->alist dtd dict))) ;; delete (let () - (define-values - (dict value) - (dict-search! dtd (alist->dict '((a . b) (c . d))) 'a - (lambda args - (error "shouldn't happen")) - (lambda (key value update delete) - (delete 'foo)))) - (test-equal '((c . d)) (dict->alist dtd dict)) - (test-equal value 'foo))) - - (test-group - "dict-copy" - (define original-dict (alist->dict '((a . b)))) - (define copied-dict (dict-copy dtd original-dict)) - (set! original-dict (dict-set! dtd original-dict 'c 'd)) - (test-equal 'd (dict-ref dtd original-dict 'c)) - (test-equal #f (dict-ref/default dtd copied-dict 'c #f))) + (define dict (dict-alter! dtd (alist->dict '((a . b) (c . d))) 'a + (lambda args + (error "shouldn't happen")) + (lambda (key value update delete) + (delete)))) + (test-equal '((c . d)) (dict->alist dtd dict)))) (test-group "dict-size" @@ -488,17 +565,6 @@ (test-equal 0 (dict-size dtd (alist->dict '())))) (test-group - "dict-for-each" - (define lst '()) - (dict-for-each dtd - (lambda (key value) - (set! lst (append lst (list key value)))) - (alist->dict '((a . b) (c . d)))) - (test-assert - (or (equal? '(a b c d) lst) - (equal? '(c d a b) lst)))) - - (test-group "dict-count" (define count (dict-count dtd (lambda (key value) @@ -617,6 +683,166 @@ (let ((cmp (dict-comparator dtd (alist->dict '((a . b)))))) (test-assert (or (not cmp) (comparator? cmp))))) + + (test-group + "dict-for-each" + (test-for-each #t + (lambda (proc) + (dict-for-each dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))))) + '(1 2 3 4))) + + (test-group + "dict-for-each<" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each< dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 3)) + '(1 2))) + + (test-group + "dict-for-each<=" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each<= dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 3)) + '(1 2 3))) + + (test-group + "dict-for-each>" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each> dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 2)) + '(3 4))) + + (test-group + "dict-for-each>=" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each>= dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 2)) + '(2 3 4))) + + (test-group + "dict-for-each-in-open-interval" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each-in-open-interval dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 1 4)) + '(2 3))) + + (test-group + "dict-for-each-in-closed-interval" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each-in-closed-interval dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 1 4)) + '(1 2 3 4))) + + (test-group + "dict-for-each-in-open-closed-interval" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each-in-open-closed-interval dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 1 4)) + '(2 3 4))) + + (test-group + "dict-for-each-in-closed-open-interval" + (test-for-each (let* ((cmp (dict-comparator dtd (alist->dict '()))) + (ordering (and cmp (comparator-ordering-predicate cmp)))) + ordering) + (lambda (proc) + (dict-for-each-in-closed-open-interval dtd + proc + (alist->dict '((1 . a) + (2 . b) + (3 . c) + (4 . d))) + 1 4)) + '(1 2 3))) + + (test-group + "make-dict-generator" + (test-for-each #t + (lambda (proc) + (generator-for-each + (lambda (entry) + (proc (car entry) (cdr entry))) + (make-dict-generator dtd (alist->dict '((1 . a) + (2 . b) + (3 . c)))))) + '(1 2 3))) + + (test-group + "dict-set-accumulator" + (define acc (dict-set-accumulator dtd (alist->dict '()))) + (acc (cons 1 'a)) + (acc (cons 2 'b)) + (acc (cons 2 'c)) + (test-assert (dict=? dtd equal? (acc (eof-object)) (alist->dict '((1 . a) (2 . c)))))) + + (test-group + "dict-adjoin-accumulator" + (define acc (dict-adjoin-accumulator dtd (alist->dict '()))) + (acc (cons 1 'a)) + (acc (cons 2 'b)) + (acc (cons 2 'c)) + (test-assert (dict=? dtd equal? (acc (eof-object)) (alist->dict '((1 . a) (2 . b)))))) ;; check all procs were called (for-each @@ -633,17 +859,18 @@ (define alist-dtd (make-alist-dtd equal?)) (define minimal-alist-dtd (make-dtd - make-dictionary-id (dtd-ref alist-dtd make-dictionary-id) dictionary?-id (dtd-ref alist-dtd dictionary?-id) + dict-mutable?-id (dtd-ref alist-dtd dict-mutable?-id) dict-size-id (dtd-ref alist-dtd dict-size-id) - dict-search-id (dtd-ref alist-dtd dict-search-id) - dict-search!-id (dtd-ref alist-dtd dict-search!-id) + dict-alter-id (dtd-ref alist-dtd dict-alter-id) dict-for-each-id (dtd-ref alist-dtd dict-for-each-id) dict-comparator-id (dtd-ref alist-dtd dict-comparator-id))) (do-test minimal-alist-dtd alist-copy - #f)) + #f + #f + )) (test-group "alist" @@ -652,7 +879,8 @@ ;; copy to a mutable list instead of using identity function ;; so that mutating procedures don't fail alist-copy - #f) + #f + #f) (test-group "alist dict-comparator" @@ -667,6 +895,7 @@ (map (lambda (pair) (list (car pair) (cdr pair))) alist))) + #f #f) (test-group "plist dict-comparator" @@ -683,8 +912,10 @@ (t69-hash-table-set! table (car pair) (cdr pair))) alist) table) - (make-default-comparator))) + (make-default-comparator) + #t)) +#| (test-group "srfi-125" (do-test @@ -744,5 +975,6 @@ (test-group "srfi-146 hash dict-comparator" (test-equal cmp (dict-comparator hash-mapping-dtd (make-dictionary hash-mapping-dtd cmp))))) +|# (test-end) diff --git a/srfi-225.html b/srfi-225.html index b715ec5..c4cee15 100644 --- a/srfi-225.html +++ b/srfi-225.html @@ -78,8 +78,8 @@ Consequently, previous examples don't affect later ones. <blockquote><pre> (define dicta '((5 . 6) (3 . 4) (1 . 2)) (define dictb '((1 . 2) (3 . 4)) -(dict=? aed dict dicta) => #t -(dict=? aed dict dictb) => #f</pre></blockquote> +(dict=? aed = dict dicta) => #t +(dict=? aed = dict dictb) => #f</pre></blockquote> <p><code>(dict-mutable?</code> <em>dtd dict</em><code>)</code></p> <p>Returns <code>#t</code> if the dictionary type supports mutations and <code>#f</code> if it supports functional updates.</p> <blockquote><pre> @@ -103,7 +103,7 @@ Consequently, previous examples don't affect later ones. (dict-max-key aed dict) => 5 </pre></blockquote> <h3 id="mutation">Functional update and mutation</h3> -<p>All these procedures exist in pairs, with and without a final <code>!</code>. The ones without <code>!</code> are functional: they never side-effect their arguments, but the result may share structure with the <em>dict</em> argument. The ones with <code>!</code> are mutations: they they change the <em>dict</em> argument. However, only one set of procedures is supported in any dictionary: for example, SRFI 125 hash tables support only mutation, whereas SRFI 146 mappings support only functional update. The <code>dict-mutable?</code> procedure can be used to determine which set is usable.</p> +<p>All these procedures exist in pairs, with and without a final <code>!</code>. The ones without <code>!</code> are functional: they never side-effect their arguments, but the result may share structure with the <em>dict</em> argument. The ones with <code>!</code> are mutations: they change the <em>dict</em> argument. However, only one set of procedures is supported in any dictionary: for example, SRFI 125 hash tables support only mutation, whereas SRFI 146 mappings support only functional update. The <code>dict-mutable?</code> procedure can be used to determine which set is usable.</p> <p><code>(dict-set</code> <em>dtd dict obj</em> …<code>)</code><br> <code>(dict-set!</code> <em>dtd dict obj</em> …<code>)</code></p> <p>Returns a dictionary that contains all the associations of <em>dict</em> plus those specified by <em>objs</em>, which alternate between keys and values. If a key to be added already exists in <em>dict</em>, the new value prevails.</p> @@ -303,6 +303,7 @@ and <code>dict-alter</code>. <code>dictionary?-id</code>, <code>dict-comparator-id</code>, <code>dict-mutable?-id</code>, +<code>dict-for-each-id</code>, <code>dict-map-id</code> (functional-update dictionaries), <code>dict-filter-id</code> (functional-update dictionaries), <code>dict-alter-id</code>, @@ -335,20 +336,19 @@ Note that it is not an error to omit any of these, but some dictionary procedure <code>dict-values-id</code>, <code>dict-entries-id</code>, <code>dict-fold-id</code>, -<code>dict-map->list-id</code>, -<code>dict->alist-id</code>, -<code>dict-for-each-id</code>, +<code>dict-map->list-id</code>, +<code>dict->alist-id</code>, <code>dict-for-each<-id</code>, <code>dict-for-each<=-id</code>, -<code>dict-for-each>-id</code>, -<code>dict-for-each>=-id</code>, +<code>dict-for-each>-id</code>, +<code>dict-for-each>=-id</code>, <code>dict-for-each-in-open-interval-id</code>, <code>dict-for-each-in-closed-interval-id</code>, <code>dict-for-each-in-open-closed-interval-id</code>, <code>dict-for-each-in-closed-open-interval-id</code>, -<code>make-dict-generator</code>, -<code>dict-set-accumulator</code>, -<code>dict-adjoin-accumulator</code>. +<code>make-dict-generator-id</code>, +<code>dict-set-accumulator-id</code>, +<code>dict-adjoin-accumulator-id</code>. <p>The <code>dtd</code> macro behaves like a wrapper around <code>make-dtd</code>, but may also verify that the <em>proc-ids</em> are valid, that there are no duplicates, etc.</p> <p><code>(make-alist-dtd</code> <em>equal</em><code>)</code></p> diff --git a/srfi/225.sld b/srfi/225.sld index 17358c4..c93f579 100644 --- a/srfi/225.sld +++ b/srfi/225.sld @@ -13,18 +13,18 @@ (export - ;; constructor - make-dictionary - dict-unfold - ;; predicates dictionary? dict-empty? dict-contains? + dict=? + dict-mutable? ;; lookup dict-ref dict-ref/default + dict-min-key + dict-max-key ;; mutation dict-set @@ -51,13 +51,11 @@ dict-filter! dict-remove dict-remove! - dict-search - dict-search! + dict-alter + dict-alter! ;; whole dictionary - dict-copy dict-size - dict-for-each dict-count dict-any dict-every @@ -69,56 +67,59 @@ dict->alist dict-comparator + ;; iteration + dict-for-each + dict-for-each< + dict-for-each<= + dict-for-each> + dict-for-each>= + dict-for-each-in-open-interval + dict-for-each-in-closed-interval + dict-for-each-in-open-closed-interval + dict-for-each-in-closed-open-interval + + ;; generator procedures + make-dict-generator + dict-set-accumulator + dict-adjoin-accumulator + ;; dictionary type descriptors dtd? make-dtd dtd - make-modified-dtd make-alist-dtd dtd-ref ;; exceptions + dictionary-error dictionary-error? dictionary-message dictionary-irritants ;; proc indeces - make-dictionary-id - dict-unfold-id dictionary?-id dict-empty?-id dict-contains?-id + dict=?-id + dict-mutable?-id dict-ref-id dict-ref/default-id + dict-min-key-id + dict-max-key-id dict-set-id - dict-set!-id dict-adjoin-id - dict-adjoin!-id dict-delete-id - dict-delete!-id dict-delete-all-id - dict-delete-all!-id dict-replace-id - dict-replace!-id dict-intern-id - dict-intern!-id dict-update-id - dict-update!-id dict-update/default-id - dict-update/default!-id dict-pop-id - dict-pop!-id dict-map-id - dict-map!-id dict-filter-id - dict-filter!-id dict-remove-id - dict-remove!-id - dict-search-id - dict-search!-id - dict-copy-id + dict-alter-id dict-size-id - dict-for-each-id dict-count-id dict-any-id dict-every-id @@ -129,6 +130,18 @@ dict-map->list-id dict->alist-id dict-comparator-id + dict-for-each-id + dict-for-each<-id + dict-for-each<=-id + dict-for-each>-id + dict-for-each>=-id + dict-for-each-in-open-interval-id + dict-for-each-in-closed-interval-id + dict-for-each-in-open-closed-interval-id + dict-for-each-in-closed-open-interval-id + make-dict-generator-id + dict-set-accumulator-id + dict-adjoin-accumulator-id ;; basic DTDs plist-dtd @@ -158,6 +171,7 @@ (export srfi-69-dtd)) (else)) +#| (cond-expand ((library (srfi 125)) (import (prefix (srfi 125) t125-)) @@ -179,4 +193,7 @@ (include "srfi-146-impl.scm" "srfi-146-hash-impl.scm") (export mapping-dtd - hash-mapping-dtd)))) + hash-mapping-dtd)) + (else)) +|# +) diff --git a/srfi/alist-impl.scm b/srfi/alist-impl.scm index 59fac7b..4400602 100644 --- a/srfi/alist-impl.scm +++ b/srfi/alist-impl.scm @@ -1,14 +1,12 @@ (define (make-alist-dtd key=) - (define (make-alist dtd comparator) - (when comparator - (raise (dictionary-error "alist dtd doesn't accept comparator" dtd))) - '()) - (define (alist? dtd l) (and (list? l) (or (null? l) (pair? (car l))))) + + (define (alist-mutable? dtd alist) + #f) (define (alist-map dtd proc alist) (map @@ -18,76 +16,49 @@ (cons key (proc key value))) alist)) - (define (alist-map! dtd proc alist) - (map! - (lambda (e) - (define key (car e)) - (define value (cdr e)) - (cons key (proc key value))) - alist)) - (define (alist-filter dtd pred alist) (filter (lambda (e) (pred (car e) (cdr e))) alist)) - (define (alist-filter! dtd pred alist) - (filter! - (lambda (e) - (pred (car e) (cdr e))) - alist)) - (define (alist-delete dtd key alist) (filter (lambda (entry) (not (key= (car entry) key))) alist)) - (define (alist-delete! dtd key alist) - (filter! - (lambda (entry) - (not (key= (car entry) key))) - alist)) - - (define (alist-search* dtd alist-delete-proc alist key failure success) + (define (alist-alter dtd alist key failure success) (define (handle-success pair) (define old-key (car pair)) (define old-value (cdr pair)) - (define (update new-key new-value obj) + (define (update new-key new-value) (cond ((and (eq? old-key new-key) (eq? old-value new-value)) - (values alist obj)) + alist) (else (let ((new-list (alist-cons new-key new-value - (alist-delete-proc dtd old-key alist)))) - (values new-list obj))))) - (define (remove obj) - (values (alist-delete-proc dtd old-key alist) obj)) + (alist-delete dtd old-key alist)))) + new-list)))) + (define (remove) + (alist-delete dtd old-key alist)) (success old-key old-value update remove)) (define (handle-failure) - (define (insert value obj) - (values (alist-cons key value alist) - obj)) - (define (ignore obj) - (values alist obj)) + (define (insert value) + (alist-cons key value alist)) + (define (ignore) + alist) (failure insert ignore)) (cond ((assoc key alist key=) => handle-success) (else (handle-failure)))) - (define (alist-search dtd alist key failure success) - (alist-search* dtd alist-delete alist key failure success)) - - (define (alist-search! dtd alist key failure success) - (alist-search* dtd alist-delete! alist key failure success)) - (define (alist-size dtd alist) (length alist)) @@ -96,32 +67,22 @@ (proc (car e) (cdr e))) (for-each proc* alist)) - (define (alist-copy dtd alist) - (map - (lambda (e) - (cons (car e) (cdr e))) - alist)) - (define (alist->alist dtd alist) - (alist-copy dtd alist)) + alist) (define (alist-comparator dtd dictionary) #f) (make-dtd - make-dictionary-id make-alist dictionary?-id alist? + dict-mutable?-id alist-mutable? dict-map-id alist-map - dict-map!-id alist-map! dict-filter-id alist-filter - dict-filter!-id alist-filter! - dict-search-id alist-search - dict-search!-id alist-search! + dict-alter-id alist-alter dict-size-id alist-size dict-for-each-id alist-foreach dict->alist-id alist->alist - dict-comparator-id alist-comparator - dict-copy-id alist-copy)) + dict-comparator-id alist-comparator)) (define alist-eqv-dtd (make-alist-dtd eqv?)) (define alist-equal-dtd (make-alist-dtd equal?)) diff --git a/srfi/default-impl.scm b/srfi/default-impl.scm index 2be8c98..24aa197 100644 --- a/srfi/default-impl.scm +++ b/srfi/default-impl.scm @@ -8,48 +8,75 @@ (define (not-implemented name) (lambda (dtd . args) (raise (dictionary-error (string-append name " not implemented") dtd)))) - (define default-make-dictionary (not-implemented "make-dictionary")) (define default-dictionary? (not-implemented "dictionary?")) + (define default-dict-mutable? (not-implemented "dict-mutable?")) (define default-dict-size (not-implemented "dict-size")) - (define default-dict-search (not-implemented "dict-search")) - (define default-dict-search! (not-implemented "dict-search!")) - (define default-dict-for-each (not-implemented "dict-for-each")) - - (define (default-dict-unfold dtd comparator stop? mapper successor seed) - (let loop ((dict (make-dictionary dtd comparator)) - (seed seed)) - (if (stop? seed) - dict - (let () - (define-values (key value) (mapper seed)) - (define new-seed (successor seed)) - (loop (dict-set! dtd dict key value) - new-seed))))) + (define default-dict-alter (not-implemented "dict-alter")) + + (define (dict-alter* dtd dict key fail success) + (if (dict-mutable? dtd dict) + (dict-alter! dtd dict key fail success) + (dict-alter dtd dict key fail success))) (define (default-dict-empty? dtd dictionary) (= 0 (dict-size dtd dictionary))) + + (define (default-dict=? dtd = dict1 dict2) + (define (check-entries* keys) + (cond + ((null? keys) #t) + (else (let* ((key (car keys)) + (d1-value (dict-ref dtd dict1 key))) + (dict-ref dtd dict2 key + (lambda () #f) + (lambda (d2-value) + (if (= d1-value d2-value) + (check-entries* (cdr keys)) + #f))))))) + (and (= (dict-size dtd dict1) + (dict-size dtd dict2)) + (check-entries* (dict-keys dtd dict1)))) (define (default-dict-contains? dtd dictionary key) (dict-ref dtd dictionary key - (lambda () #f) (lambda (x) #t))) + (lambda () #f) + (lambda (x) #t))) (define (default-dict-ref dtd dictionary key failure success) - (define-values - (new-dict result) - (dict-search dtd dictionary key - (lambda (_ ignore) - (ignore (failure))) - (lambda (key value update _) - (update key value (success value))))) - result) + (dict-alter* dtd dictionary key + (lambda (insert ignore) + (failure)) + (lambda (key value update remove) + (success value)))) (define (default-dict-ref/default dtd dictionary key default) (dict-ref dtd dictionary key (lambda () default) (lambda (x) x))) + + (define (default-dict-find-key dtd dict cmp-proc) + (define cmp (dict-comparator dtd dict)) + (define keys (dict-keys dtd dict)) + (when (not cmp) + (raise (dictionary-error "dictionary doesn't have comparator"))) + (when (null? keys) + (error "Cannot find min/max key in empty dictionary")) + (let loop ((best (car keys)) + (keys (cdr keys))) + (cond + ((null? keys) best) + ((cmp-proc cmp (car keys) best) + (loop (car keys) (cdr keys))) + (else (loop best (cdr keys)))))) + + (define (default-dict-min-key dtd dict) + (default-dict-find-key dtd dict <?)) + + (define (default-dict-max-key dtd dict) + (default-dict-find-key dtd dict >?)) ;; private - (define (default-dict-set* dtd dictionary dict-search-proc use-old? objs) + (define (default-dict-set* dtd dictionary use-old? objs) (let loop ((objs objs) (dictionary dictionary)) (cond @@ -57,101 +84,60 @@ dictionary) ((null? (cdr objs)) (error "mismatch of key / values argument list" objs)) - (else (let*-values - (((key) (car objs)) - ((value) (cadr objs)) - ((new-d _) (dict-search-proc dtd dictionary key - (lambda (insert ignore) - (insert value #f)) - (lambda (key old-value update delete) - (update key (if use-old? old-value value) #f))))) + (else (let* ((key (car objs)) + (value (cadr objs)) + (new-d (dict-alter* dtd dictionary key + (lambda (insert ignore) + (insert value)) + (lambda (key old-value update delete) + (update key (if use-old? old-value value)))))) (loop (cddr objs) new-d)))))) (define (default-dict-set dtd dictionary . objs) - (default-dict-set* dtd dictionary dict-search #f objs)) - - (define (default-dict-set! dtd dictionary . objs) - (default-dict-set* dtd dictionary dict-search! #f objs)) + (default-dict-set* dtd dictionary #f objs)) (define (default-dict-adjoin dtd dictionary . objs) - (default-dict-set* dtd dictionary dict-search #t objs)) - - (define (default-dict-adjoin! dtd dictionary . objs) - (default-dict-set* dtd dictionary dict-search! #t objs)) + (default-dict-set* dtd dictionary #t objs)) (define (default-dict-delete dtd dictionary . keys) (dict-delete-all dtd dictionary keys)) - (define (default-dict-delete! dtd dictionary . keys) - (dict-delete-all! dtd dictionary keys)) - - (define (default-dict-delete-all* dtd dictionary dict-search-proc keylist) + (define (default-dict-delete-all dtd dictionary keylist) (let loop ((keylist keylist) (d dictionary)) (cond - ((null? keylist) d) - (else (let*-values - (((key) (car keylist)) - ((new-d _) (dict-search-proc dtd d key - (lambda (_ ignore) - (ignore #f)) - (lambda (key old-value _ delete) - (delete #f))))) - (loop (cdr keylist) - new-d)))))) - - (define (default-dict-delete-all dtd dictionary keylist) - (default-dict-delete-all* dtd dictionary dict-search keylist)) - - (define (default-dict-delete-all! dtd dictionary keylist) - (default-dict-delete-all* dtd dictionary dict-search! keylist)) - - (define (default-dict-replace* dtd dictionary dict-search-proc key value) - (define-values - (new-dict _) - (dict-search-proc dtd dictionary key - (lambda (_ ignore) - (ignore #f)) - (lambda (key old-value update _) - (update key value #f)))) - new-dict) + ((null? keylist) d) + (else (let* ((key (car keylist)) + (new-d (dict-alter* dtd d key + (lambda (_ ignore) + (ignore)) + (lambda (key old-value _ delete) + (delete))))) + (loop (cdr keylist) + new-d)))))) (define (default-dict-replace dtd dictionary key value) - (default-dict-replace* dtd dictionary dict-search key value)) - - (define (default-dict-replace! dtd dictionary key value) - (default-dict-replace* dtd dictionary dict-search! key value)) - - (define (default-dict-intern* dtd dictionary dict-search-proc key failure) - (dict-search-proc dtd dictionary key - (lambda (insert _) - (let ((value (failure))) - (insert value value))) - (lambda (key value update _) - (update key value value)))) + (dict-alter* dtd dictionary key + (lambda (_ ignore) + (ignore)) + (lambda (key old-value update _) + (update key value)))) (define (default-dict-intern dtd dictionary key failure) - (default-dict-intern* dtd dictionary dict-search key failure)) - - (define (default-dict-intern! dtd dictionary key failure) - (default-dict-intern* dtd dictionary dict-search! key failure)) - - (define (default-dict-update* dtd dictionary dict-search-proc key updater failure success) - (define-values - (new-dict _) - (dict-search-proc dtd dictionary key - (lambda (insert ignore) - (insert (updater (failure)) #f)) - (lambda (key value update _) - (update key (updater (success value)) #f)))) - new-dict) + (dict-alter* dtd dictionary key + (lambda (insert _) + (let ((value (failure))) + (values (insert value) value))) + (lambda (key value update _) + (values dictionary value)))) (define (default-dict-update dtd dictionary key updater failure success) - (default-dict-update* dtd dictionary dict-search key updater failure success)) - - (define (default-dict-update! dtd dictionary key updater failure success) - (default-dict-update* dtd dictionary dict-search! key updater failure success)) + (dict-alter* dtd dictionary key + (lambda (insert ignore) + (insert (updater (failure)))) + (lambda (key value update _) + (update key (updater (success value)))))) (define (default-dict-update/default* dtd dictionary dict-update-proc key updater default) (dict-update-proc dtd dictionary key updater @@ -159,19 +145,18 @@ (lambda (x) x))) (define (default-dict-update/default dtd dictionary key updater default) - (default-dict-update/default* dtd dictionary dict-update key updater default)) - - (define (default-dict-update/default! dtd dictionary key updater default) - (default-dict-update/default* dtd dictionary dict-update! key updater default)) + (dict-update dtd dictionary key updater + (lambda () default) + (lambda (x) x))) - (define (default-dict-pop* dtd dictionary dict-delete-proc) + (define (default-dict-pop dtd dictionary) (define (do-pop) (call/cc (lambda (cont) (dict-for-each dtd (lambda (key value) (define new-dict - (dict-delete-proc dtd dictionary key)) + (dict-delete dtd dictionary key)) (cont new-dict key value)) dictionary)))) (define empty? (dict-empty? dtd dictionary)) @@ -179,13 +164,7 @@ (error "popped empty dictionary") (do-pop))) - (define (default-dict-pop dtd dictionary) - (default-dict-pop* dtd dictionary dict-delete)) - - (define (default-dict-pop! dtd dictionary) - (default-dict-pop* dtd dictionary dict-delete!)) - - (define (default-dict-map* dtd dict-replace-proc mapper dictionary) + (define (default-dict-map dtd mapper dictionary) (define keys (dict-keys dtd dictionary)) (let loop ((keys keys) (dict dictionary)) @@ -194,48 +173,21 @@ (let* ((key (car keys)) (val (mapper key (dict-ref dtd dict key)))) (loop (cdr keys) - (dict-replace-proc dtd dict key val)))))) - - (define (default-dict-map dtd mapper dictionary) - (default-dict-map* dtd dict-replace mapper dictionary)) - - (define (default-dict-map! dtd mapper dictionary) - (default-dict-map* dtd dict-replace! mapper dictionary)) + (dict-replace dtd dict key val)))))) - (define (default-dict-filter* dtd dict-delete-all-proc pred dictionary) + (define (default-dict-filter dtd pred dictionary) (define keys (dict-keys dtd dictionary)) (define keys-to-delete (filter (lambda (key) (not (pred key (dict-ref dtd dictionary key)))) keys)) - (dict-delete-all-proc dtd dictionary keys-to-delete)) - - (define (default-dict-filter dtd pred dictionary) - (default-dict-filter* dtd dict-delete-all pred dictionary)) - - (define (default-dict-filter! dtd pred dictionary) - (default-dict-filter* dtd dict-delete-all! pred dictionary)) - - (define (default-dict-remove* dtd dict-filter-proc pred dictionary) - (dict-filter-proc dtd - (lambda (key value) - (not (pred key value))) - dictionary)) + (dict-delete-all dtd dictionary keys-to-delete)) (define (default-dict-remove dtd pred dictionary) - (default-dict-remove* dtd dict-filter pred dictionary)) - - (define (default-dict-remove! dtd pred dictionary) - (default-dict-remove* dtd dict-filter! pred dictionary)) - - (define (default-dict-copy dtd dictionary) - (define dict (make-dictionary dtd (dict-comparator dtd dictionary))) - (dict-for-each dtd - (lambda (key value) - (set! dict (dict-set! dtd dict key value))) - dictionary) - dict) + (dict-filter dtd (lambda (key value) + (not (pred key value))) + dictionary)) (define (default-dict-count dtd pred dictionary) (dict-fold dtd @@ -320,48 +272,122 @@ dictionary)) (define default-dict-comparator (not-implemented "dict-comparator")) + + (define default-dict-for-each (not-implemented "dict-for-each")) + + (define (default-dict-for-each/filtered dtd pred proc dict) + (dict-for-each dtd + (lambda (key value) + (when (pred key) + (proc key value))) + dict)) + + (define (default-dict-for-each< dtd proc dict key) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (<? cmp k key)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each<= dtd proc dict key) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (<=? cmp k key)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each> dtd proc dict key) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (>? cmp k key)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each>= dtd proc dict key) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (>? cmp k key)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each-in-open-interval dtd proc dict key1 key2) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (<? cmp key1 k key2)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each-in-closed-interval dtd proc dict key1 key2) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (<=? cmp key1 k key2)) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each-in-open-closed-interval dtd proc dict key1 key2) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (and (<? cmp key1 k) + (<=? cmp k key2))) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-dict-for-each-in-closed-open-interval dtd proc dict key1 key2) + (define cmp (dict-comparator dtd dict)) + (define (pred k) + (and (<=? cmp key1 k) + (<? cmp k key2))) + (default-dict-for-each/filtered dtd pred proc dict)) + + (define (default-make-dict-generator dtd dict) + (define-values (keys vals) + (dict-entries dtd dict)) + (lambda () + (if (null? keys) + (eof-object) + (let ((key (car keys)) + (value (car vals))) + (set! keys (cdr keys)) + (set! vals (cdr vals)) + (cons key value))))) + + (define (default-dict-accumulator dtd dict acc-proc) + (lambda (arg) + (if (eof-object? arg) + dict + (set! dict (acc-proc dtd dict (car arg) (cdr arg)))))) + + (define (default-dict-set-accumulator dtd dict) + (if (dict-mutable? dtd dict) + (default-dict-accumulator dtd dict dict-set!) + (default-dict-accumulator dtd dict dict-set))) + + (define (default-dict-adjoin-accumulator dtd dict) + (if (dict-mutable? dtd dict) + (default-dict-accumulator dtd dict dict-adjoin!) + (default-dict-accumulator dtd dict dict-adjoin))) (let () (define null-dtd (make-dtd-private (make-vector dict-procedures-count #f))) (define default-dtd (make-modified-dtd null-dtd - make-dictionary-id default-make-dictionary - dict-unfold-id default-dict-unfold dictionary?-id default-dictionary? dict-empty?-id default-dict-empty? dict-contains?-id default-dict-contains? + dict=?-id default-dict=? + dict-mutable?-id default-dict-mutable? dict-ref-id default-dict-ref dict-ref/default-id default-dict-ref/default + dict-min-key-id default-dict-min-key + dict-max-key-id default-dict-max-key dict-set-id default-dict-set - dict-set!-id default-dict-set! dict-adjoin-id default-dict-adjoin - dict-adjoin!-id default-dict-adjoin! dict-delete-id default-dict-delete - dict-delete!-id default-dict-delete! dict-delete-all-id default-dict-delete-all - dict-delete-all!-id default-dict-delete-all! dict-replace-id default-dict-replace - dict-replace!-id default-dict-replace! dict-intern-id default-dict-intern - dict-intern!-id default-dict-intern! dict-update-id default-dict-update - dict-update!-id default-dict-update! dict-update/default-id default-dict-update/default - dict-update/default!-id default-dict-update/default! dict-pop-id default-dict-pop - dict-pop!-id default-dict-pop! dict-map-id default-dict-map - dict-map!-id default-dict-map! dict-filter-id default-dict-filter - dict-filter!-id default-dict-filter! dict-remove-id default-dict-remove - dict-remove!-id default-dict-remove! - dict-search-id default-dict-search - dict-search!-id default-dict-search! - dict-copy-id default-dict-copy + dict-alter-id default-dict-alter dict-size-id default-dict-size - dict-for-each-id default-dict-for-each dict-count-id default-dict-count dict-any-id default-dict-any dict-every-id default-dict-every @@ -371,7 +397,22 @@ dict-fold-id default-dict-fold dict-map->list-id default-dict-map->list dict->alist-id default-dict->alist - dict-comparator-id default-dict-comparator)) + dict-comparator-id default-dict-comparator + + dict-for-each-id default-dict-for-each + dict-for-each<-id default-dict-for-each< + dict-for-each<=-id default-dict-for-each<= + dict-for-each>-id default-dict-for-each> + dict-for-each>=-id default-dict-for-each> + dict-for-each-in-open-interval-id default-dict-for-each-in-open-interval + dict-for-each-in-closed-interval-id default-dict-for-each-in-closed-interval + dict-for-each-in-open-closed-interval-id default-dict-for-each-in-open-closed-interval + dict-for-each-in-closed-open-interval-id default-dict-for-each-in-closed-open-interval + + ;; generator procedures + make-dict-generator-id default-make-dict-generator + dict-set-accumulator-id default-dict-set-accumulator + dict-adjoin-accumulator-id default-dict-adjoin-accumulator)) ;; sanity check (vector-for-each diff --git a/srfi/externals.scm b/srfi/externals.scm index 14c5a4d..8b0bf8e 100644 --- a/srfi/externals.scm +++ b/srfi/externals.scm @@ -11,12 +11,14 @@ (message dictionary-message) (irritants dictionary-irritants)) +;; shorthand access to dtd procedure by index (define-syntax dtd-ref-stx (syntax-rules () ((_ dtd index) (begin (vector-ref (procvec dtd) index))))) +;; shorthand to define proc with using proc index (define-syntax define/dict-proc (syntax-rules () ((_ proc index) @@ -24,11 +26,43 @@ (assume (dtd? dtd)) (apply (dtd-ref-stx dtd index) dtd args))))) -(define/dict-proc make-dictionary make-dictionary-id) -(define/dict-proc dict-unfold dict-unfold-id) +;; define mutable and immutable versions of a procedure (such as dict-set! and dict-set) +;; with appropriate assertion for dict-mutable? value +;; when dtd is first arg, and dict is second arg +(define-syntax define/dict-proc-pair + (syntax-rules () + ((_ proc-immutable proc-mutable index) + (begin + (define (proc-mutable dtd dict . args) + (assume (dtd? dtd)) + (assume ((dtd-ref-stx dtd dict-mutable?-id) dtd dict)) + (apply (dtd-ref-stx dtd index) dtd dict args)) + (define (proc-immutable dtd dict . args) + (assume (dtd? dtd)) + (assume (not ((dtd-ref-stx dtd dict-mutable?-id) dtd dict)) index) + (apply (dtd-ref-stx dtd index) dtd dict args)))))) + +;; define mutable and immutable versions of a procedure (such as dict-set! and dict-set) +;; with appropriate assertion for dict-mutable? value +;; when dtd is first arg, and dict is third arg (ie filter, map shape signature) +(define-syntax define/dict-proc-pair* + (syntax-rules () + ((_ proc-immutable proc-mutable index) + (begin + (define (proc-mutable dtd proc dict) + (assume (dtd? dtd)) + (assume ((dtd-ref-stx dtd dict-mutable?-id) dtd dict)) + ((dtd-ref-stx dtd index) dtd proc dict)) + (define (proc-immutable dtd proc dict) + (assume (dtd? dtd)) + (assume (not ((dtd-ref-stx dtd dict-mutable?-id) dtd dict))) + ((dtd-ref-stx dtd index) dtd proc dict)))))) + (define/dict-proc dictionary? dictionary?-id) (define/dict-proc dict-empty? dict-empty?-id) (define/dict-proc dict-contains? dict-contains?-id) +(define/dict-proc dict-mutable? dict-mutable?-id) +(define/dict-proc dict=? dict=?-id) (define dict-ref (case-lambda @@ -45,18 +79,14 @@ ((dtd-ref-stx dtd dict-ref-id) dtd dict key failure success)))) (define/dict-proc dict-ref/default dict-ref/default-id) -(define/dict-proc dict-set dict-set-id) -(define/dict-proc dict-set! dict-set!-id) -(define/dict-proc dict-adjoin dict-adjoin-id) -(define/dict-proc dict-adjoin! dict-adjoin!-id) -(define/dict-proc dict-delete dict-delete-id) -(define/dict-proc dict-delete! dict-delete!-id) -(define/dict-proc dict-delete-all dict-delete-all-id) -(define/dict-proc dict-delete-all! dict-delete-all!-id) -(define/dict-proc dict-replace dict-replace-id) -(define/dict-proc dict-replace! dict-replace!-id) -(define/dict-proc dict-intern dict-intern-id) -(define/dict-proc dict-intern! dict-intern!-id) +(define/dict-proc dict-min-key dict-min-key-id) +(define/dict-proc dict-max-key dict-max-key-id) +(define/dict-proc-pair dict-set dict-set! dict-set-id) +(define/dict-proc-pair dict-adjoin dict-adjoin! dict-adjoin-id) +(define/dict-proc-pair dict-delete dict-delete! dict-delete-id) +(define/dict-proc-pair dict-delete-all dict-delete-all! dict-delete-all-id) +(define/dict-proc-pair dict-replace dict-replace! dict-replace-id) +(define/dict-proc-pair dict-intern dict-intern! dict-intern-id) (define dict-update (case-lambda @@ -70,37 +100,31 @@ ((dtd dict key updater failure success) (assume (dtd? dtd)) + (assume (not ((dtd-ref-stx dtd dict-mutable?-id) dtd dict))) ((dtd-ref-stx dtd dict-update-id) dtd dict key updater failure success)))) (define dict-update! (case-lambda ((dtd dict key updater) - (dict-update! dtd dict key updater - (lambda () (error "Key not found in dictionary" dict key)) - values)) + (dict-update dtd dict key updater + (lambda () (error "Key not found in dictionary" dict key)) + values)) ((dtd dict key updater failure) - (dict-update! dtd dict key updater failure values)) + (dict-update dtd dict key updater failure values)) ((dtd dict key updater failure success) (assume (dtd? dtd)) - ((dtd-ref-stx dtd dict-update!-id) dtd dict key updater failure success)))) - -(define/dict-proc dict-update/default dict-update/default-id) -(define/dict-proc dict-update/default! dict-update/default!-id) -(define/dict-proc dict-pop dict-pop-id) -(define/dict-proc dict-pop! dict-pop!-id) -(define/dict-proc dict-map dict-map-id) -(define/dict-proc dict-map! dict-map!-id) -(define/dict-proc dict-filter dict-filter-id) -(define/dict-proc dict-filter! dict-filter!-id) -(define/dict-proc dict-remove dict-remove-id) -(define/dict-proc dict-remove! dict-remove!-id) -(define/dict-proc dict-search dict-search-id) -(define/dict-proc dict-search! dict-search!-id) -(define/dict-proc dict-copy dict-copy-id) + (assume ((dtd-ref-stx dtd dict-mutable?-id) dtd dict)) + ((dtd-ref-stx dtd dict-update-id) dtd dict key updater failure success)))) + +(define/dict-proc-pair dict-update/default dict-update/default! dict-update/default-id) +(define/dict-proc-pair dict-pop dict-pop! dict-pop-id) +(define/dict-proc-pair* dict-map dict-map! dict-map-id) +(define/dict-proc-pair* dict-filter dict-filter! dict-filter-id) +(define/dict-proc-pair* dict-remove dict-remove! dict-remove-id) +(define/dict-proc-pair dict-alter dict-alter! dict-alter-id) (define/dict-proc dict-size dict-size-id) -(define/dict-proc dict-for-each dict-for-each-id) (define/dict-proc dict-count dict-count-id) (define/dict-proc dict-any dict-any-id) (define/dict-proc dict-every dict-every-id) @@ -111,6 +135,18 @@ (define/dict-proc dict-map->list dict-map->list-id) (define/dict-proc dict->alist dict->alist-id) (define/dict-proc dict-comparator dict-comparator-id) +(define/dict-proc dict-for-each dict-for-each-id) +(define/dict-proc dict-for-each< dict-for-each<-id) +(define/dict-proc dict-for-each<= dict-for-each<=-id) +(define/dict-proc dict-for-each> dict-for-each>-id) +(define/dict-proc dict-for-each>= dict-for-each>=-id) +(define/dict-proc dict-for-each-in-open-interval dict-for-each-in-open-interval-id) +(define/dict-proc dict-for-each-in-closed-interval dict-for-each-in-closed-interval-id) +(define/dict-proc dict-for-each-in-open-closed-interval dict-for-each-in-open-closed-interval-id) +(define/dict-proc dict-for-each-in-closed-open-interval dict-for-each-in-closed-open-interval-id) +(define/dict-proc make-dict-generator make-dict-generator-id) +(define/dict-proc dict-set-accumulator dict-set-accumulator-id) +(define/dict-proc dict-adjoin-accumulator dict-adjoin-accumulator-id) (define (dtd-ref dtd procindex) (dtd-ref-stx dtd procindex)) diff --git a/srfi/indexes.scm b/srfi/indexes.scm index 958f5a0..f71a76e 100644 --- a/srfi/indexes.scm +++ b/srfi/indexes.scm @@ -5,42 +5,29 @@ (define v proc-id) (set! proc-id (+ 1 proc-id)) v) -(define make-dictionary-id (proc-id-inc)) -(define dict-unfold-id (proc-id-inc)) (define dictionary?-id (proc-id-inc)) (define dict-empty?-id (proc-id-inc)) (define dict-contains?-id (proc-id-inc)) +(define dict=?-id (proc-id-inc)) +(define dict-mutable?-id (proc-id-inc)) (define dict-ref-id (proc-id-inc)) (define dict-ref/default-id (proc-id-inc)) +(define dict-min-key-id (proc-id-inc)) +(define dict-max-key-id (proc-id-inc)) (define dict-set-id (proc-id-inc)) -(define dict-set!-id (proc-id-inc)) (define dict-adjoin-id (proc-id-inc)) -(define dict-adjoin!-id (proc-id-inc)) (define dict-delete-id (proc-id-inc)) -(define dict-delete!-id (proc-id-inc)) (define dict-delete-all-id (proc-id-inc)) -(define dict-delete-all!-id (proc-id-inc)) (define dict-replace-id (proc-id-inc)) -(define dict-replace!-id (proc-id-inc)) (define dict-intern-id (proc-id-inc)) -(define dict-intern!-id (proc-id-inc)) (define dict-update-id (proc-id-inc)) -(define dict-update!-id (proc-id-inc)) (define dict-update/default-id (proc-id-inc)) -(define dict-update/default!-id (proc-id-inc)) (define dict-pop-id (proc-id-inc)) -(define dict-pop!-id (proc-id-inc)) (define dict-map-id (proc-id-inc)) -(define dict-map!-id (proc-id-inc)) (define dict-filter-id (proc-id-inc)) -(define dict-filter!-id (proc-id-inc)) (define dict-remove-id (proc-id-inc)) -(define dict-remove!-id (proc-id-inc)) -(define dict-search-id (proc-id-inc)) -(define dict-search!-id (proc-id-inc)) -(define dict-copy-id (proc-id-inc)) +(define dict-alter-id (proc-id-inc)) (define dict-size-id (proc-id-inc)) -(define dict-for-each-id (proc-id-inc)) (define dict-count-id (proc-id-inc)) (define dict-any-id (proc-id-inc)) (define dict-every-id (proc-id-inc)) @@ -51,4 +38,16 @@ (define dict-map->list-id (proc-id-inc)) (define dict->alist-id (proc-id-inc)) (define dict-comparator-id (proc-id-inc)) -(define dict-procedures-count (proc-id-inc)) +(define dict-for-each-id (proc-id-inc)) +(define dict-for-each<-id (proc-id-inc)) +(define dict-for-each<=-id (proc-id-inc)) +(define dict-for-each>-id (proc-id-inc)) +(define dict-for-each>=-id (proc-id-inc)) +(define dict-for-each-in-open-interval-id (proc-id-inc)) +(define dict-for-each-in-closed-interval-id (proc-id-inc)) +(define dict-for-each-in-open-closed-interval-id (proc-id-inc)) +(define dict-for-each-in-closed-open-interval-id (proc-id-inc)) +(define make-dict-generator-id (proc-id-inc)) +(define dict-set-accumulator-id (proc-id-inc)) +(define dict-adjoin-accumulator-id (proc-id-inc)) +(define dict-procedures-count (proc-id-inc)) ;; only used for tracking backing vector size diff --git a/srfi/plist-impl.scm b/srfi/plist-impl.scm index e283c8e..d291870 100644 --- a/srfi/plist-impl.scm +++ b/srfi/plist-impl.scm @@ -1,41 +1,29 @@ (define plist-dtd (let () - (define (make-plist dtd comparator) - (when comparator - (raise (dictionary-error "plist dtd doesn't accept comparator" dtd))) - '()) - (define (plist? dtd l) (and (list? l) (or (null? l) (symbol? (car l))))) (define (plist-map dtd proc plist) - (plist-map! dtd proc (dict-copy dtd plist))) - - (define (plist-map! dtd proc plist) - (let loop ((pl plist)) + (let loop ((pl plist) + (new-pl/rev '())) (cond - ((null? pl) plist) + ((null? pl) (reverse new-pl/rev)) ((null? (cdr pl)) (error "Malformed plist" plist)) (else (let ((key (car pl)) (value (cadr pl)) (rest (cddr pl))) - (set-car! (cdr pl) - (proc key value)) - (loop rest)))))) + (loop rest + (append (list (proc key value) key) new-pl/rev))))))) (define (plist-filter dtd pred plist) - (plist-filter! dtd pred (dict-copy dtd plist))) - - (define (plist-filter! dtd pred plist) - (define head (cons #f plist)) (let loop ((pl plist) - (parent-cell head)) + (new-pl/rev '())) (cond - ((null? pl) (cdr head)) + ((null? pl) (reverse new-pl/rev)) ((null? (cdr pl)) (error "Malformed plist" plist)) (else (let ((key (car pl)) @@ -43,54 +31,58 @@ (rest (cddr pl))) (if (pred key value) (loop rest - (cdr pl)) - (loop (begin - (set-cdr! parent-cell rest) - rest) - parent-cell))))))) + (append (list value key) new-pl/rev)) + (loop rest + new-pl/rev))))))) - ;; head is a pair, whose cdr is the plist - ;; if found, returns a pair, whose cdr is rest of plist, and cadr is key that was searched for - ;; if not found, returns #f - ;; - ;; the pair indirection is used so that calling set-cdr! on the result allows the plist to be mutated - (define (find-plist-entry key head) - (define plist (cdr head)) + (define (find-plist-entry key plist) (cond ((null? plist) #f) - ((equal? key (car plist)) head) - (else (find-plist-entry key (cdr plist))))) - - (define (plist-search dtd plist key failure success) - (plist-search! dtd (dict-copy dtd plist) key failure success)) + ((eq? key (car plist)) plist) + (else (find-plist-entry key (cddr plist))))) + + (define (plist-delete key-to-delete plist) + (let loop ((pl plist) + (new-pl/rev '())) + (cond + ((null? pl) (reverse new-pl/rev)) + ((null? (cdr pl)) (error "Malformed plist")) + (else (let ((key (car pl)) + (value (cadr pl)) + (rest (cddr pl))) + (if (eq? key-to-delete key) + (loop rest new-pl/rev) + (loop rest (append (list value key) new-pl/rev)))))))) - (define (plist-search! dtd plist key failure success) - (define plist-head (cons #t plist)) - (define (handle-success head) - (define key-cell (cdr head)) - (define val-cell (cddr head)) - (define (update new-key new-value obj) - (set-car! key-cell new-key) - (set-car! val-cell new-value) - (values plist obj)) - (define (remove obj) - (set-cdr! head (cddr (cdr head))) - (values (cdr plist-head) obj)) - (success (car key-cell) (car val-cell) update remove)) + (define (plist-alter dtd plist key failure success) + (define (handle-success pair) + (define old-key (car pair)) + (define old-value (cadr pair)) + (define (update new-key new-value) + (cond + ((and (eq? old-key + new-key) + (eq? old-value + new-value)) + plist) + (else + (let ((new-list + (append (list new-key new-value) + (plist-delete old-key plist)))) + new-list)))) + (define (remove) + (plist-delete old-key plist)) + (success old-key old-value update remove)) (define (handle-failure) - (define (insert value obj) - (values (cons key (cons value plist)) - obj)) - (define (ignore obj) - (values plist obj)) + (define (insert value) + (append (list key value) plist)) + (define (ignore) + plist) (failure insert ignore)) (cond - ((find-plist-entry key plist-head) => handle-success) - (else (handle-failure)))) - - (define (plist-copy dtd plist) - (list-copy plist)) + ((find-plist-entry key plist) => handle-success) + (else (handle-failure)))) (define (plist-size dtd plist) (/ (length plist) 2)) @@ -101,20 +93,19 @@ (begin (proc (car pl) (cadr pl)) (loop (cddr pl)))))) + + (define (plist-mutable? dtd plist) + #f) (define (plist-comparator dtd plist) #f) (make-dtd - make-dictionary-id make-plist dictionary?-id plist? + dict-mutable?-id plist-mutable? dict-map-id plist-map - dict-map!-id plist-map! dict-filter-id plist-filter - dict-filter!-id plist-filter! - dict-search-id plist-search - dict-search!-id plist-search! - dict-copy-id plist-copy + dict-alter-id plist-alter dict-size-id plist-size dict-for-each-id plist-foreach dict-comparator-id plist-comparator))) diff --git a/srfi/srfi-69-impl.scm b/srfi/srfi-69-impl.scm index 90c3b97..fe4edf3 100644 --- a/srfi/srfi-69-impl.scm +++ b/srfi/srfi-69-impl.scm @@ -4,17 +4,9 @@ (define (prep-dtd-arg proc) (lambda (dtd . args) (apply proc args))) - - (define (t69-make-hash-table* dtd comparator) - (define constructor-args - (if (not comparator) - '() - (let ((pred (comparator-equality-predicate comparator)) - (hash (comparator-hash-function comparator))) - (if hash - (list pred hash) - (list pred))))) - (apply t69-make-hash-table constructor-args)) + + (define (t69-hash-table-mutable?* dtd table) + #t) (define (t69-hash-table-ref* dtd table key fail success) (define default (cons #f #f)) @@ -57,29 +49,26 @@ (t69-hash-table-delete! table key)))) table) - (define (t69-hash-table-filter* dtd proc table) - (dict-filter! dtd proc (dict-copy dtd table))) - (define (t69-hash-table-fold* dtd proc knil table) (t69-hash-table-fold table proc knil)) - (define (t69-hash-table-search!* dtd table key fail success) + (define (t69-hash-table-alter!* dtd table key fail success) (define (handle-success value) - (define (update new-key new-value obj) + (define (update new-key new-value) (unless (eq? new-key key) (t69-hash-table-delete! table key)) (t69-hash-table-set! table new-key new-value) - (values table obj)) - (define (remove obj) + table) + (define (remove) (t69-hash-table-delete! table key) - (values table obj)) + table) (success key value update remove)) (define (handle-fail) - (define (ignore obj) - (values table obj)) - (define (insert value obj) + (define (ignore) + table) + (define (insert value) (t69-hash-table-set! table key value) - (values table obj)) + table) (fail insert ignore)) (define default (cons #f #f)) @@ -88,9 +77,6 @@ (handle-fail) (handle-success found))) - (define (t69-hash-table-search* dtd table key fail success) - (t69-hash-table-search!* dtd (dict-copy dtd table) key fail success)) - (define (t69-hash-table-comparator* dtd table) (make-comparator (lambda args #t) (or (t69-hash-table-equivalence-function table) @@ -99,24 +85,21 @@ (t69-hash-table-hash-function table))) (make-dtd - make-dictionary-id t69-make-hash-table* dictionary?-id (prep-dtd-arg t69-hash-table?) + dict-mutable?-id t69-hash-table-mutable?* dict-ref-id t69-hash-table-ref* dict-ref/default-id (prep-dtd-arg t69-hash-table-ref/default) - dict-set!-id t69-hash-table-set!* - dict-delete-all!-id t69-hash-table-delete-all!* + dict-set-id t69-hash-table-set!* + dict-delete-all-id t69-hash-table-delete-all!* dict-contains?-id (prep-dtd-arg t69-hash-table-exists?) - dict-update/default!-id t69-hash-table-update!/default* + dict-update/default-id t69-hash-table-update!/default* dict-size-id (prep-dtd-arg t69-hash-table-size) dict-keys-id (prep-dtd-arg t69-hash-table-keys) dict-values-id (prep-dtd-arg t69-hash-table-values) - dict-map!-id t69-hash-table-map!* - dict-filter!-id t69-hash-table-filter!* - dict-filter-id t69-hash-table-filter* + dict-map-id t69-hash-table-map!* + dict-filter-id t69-hash-table-filter!* dict-for-each-id t69-hash-table-foreach* dict-fold-id t69-hash-table-fold* dict->alist-id (prep-dtd-arg t69-hash-table->alist) - dict-search-id t69-hash-table-search* - dict-search!-id t69-hash-table-search!* - dict-comparator-id t69-hash-table-comparator* - dict-copy-id (prep-dtd-arg t69-hash-table-copy)))) + dict-alter-id t69-hash-table-alter!* + dict-comparator-id t69-hash-table-comparator*))) |
