77 lines
2.8 KiB
Scheme
77 lines
2.8 KiB
Scheme
#lang scheme
|
|
|
|
;; a shorthand for use below
|
|
(define-syntax ⇒
|
|
(syntax-rules ()
|
|
[(⇒ antecedent consequent) (if antecedent consequent #t)]))
|
|
|
|
;; implementation
|
|
(define-struct dictionary (l value? eq?))
|
|
;; the keys should probably be another parameter (exercise)
|
|
|
|
(define (initialize p eq) (make-dictionary '() p eq))
|
|
(define (put d k v)
|
|
(make-dictionary (cons (cons k v) (dictionary-l d))
|
|
(dictionary-value? d)
|
|
(dictionary-eq? d)))
|
|
(define (rem d k)
|
|
(make-dictionary
|
|
(let loop ([l (dictionary-l d)])
|
|
(cond
|
|
[(null? l) l]
|
|
[(eq? (caar l) k) (loop (cdr l))]
|
|
[else (cons (car l) (loop (cdr l)))]))
|
|
(dictionary-value? d)
|
|
(dictionary-eq? d)))
|
|
(define (count d) (length (dictionary-l d)))
|
|
(define (value-for d k) (cdr (assq k (dictionary-l d))))
|
|
(define (has? d k) (pair? (assq k (dictionary-l d))))
|
|
(define (not-has? d) (lambda (k) (not (has? d k))))
|
|
;; end of implementation
|
|
|
|
;; interface
|
|
(provide/contract
|
|
;; predicates
|
|
[dictionary? (-> any/c boolean?)]
|
|
;; basic queries
|
|
;; how many items are in the dictionary?
|
|
[count (-> dictionary? natural-number/c)]
|
|
;; does the dictionary define key k?
|
|
[has? (->d ([d dictionary?][k symbol?])
|
|
()
|
|
[result boolean?]
|
|
#:post-cond
|
|
((zero? (count d)) . ⇒ . (not result)))]
|
|
;; what is the value of key k in this dictionary?
|
|
[value-for (->d ([d dictionary?]
|
|
[k (and/c symbol? (lambda (k) (has? d k)))])
|
|
()
|
|
[result (dictionary-value? d)])]
|
|
;; initialization
|
|
;; post condition: for all k in symbol, (has? d k) is false.
|
|
[initialize (->d ([p contract?][eq (p p . -> . boolean?)])
|
|
()
|
|
[result (and/c dictionary? (compose zero? count))])]
|
|
;; commands
|
|
;; Mitchell and McKim say that put shouldn't consume Void (null ptr)
|
|
;; for v. We allow the client to specify a contract for all values
|
|
;; via initialize. We could do the same via a key? parameter
|
|
;; (exercise). add key k with value v to this dictionary
|
|
[put (->d ([d dictionary?]
|
|
[k (and symbol? (not-has? d))]
|
|
[v (dictionary-value? d)])
|
|
()
|
|
[result dictionary?]
|
|
#:post-cond
|
|
(and (has? result k)
|
|
(= (count d) (- (count result) 1))
|
|
([dictionary-eq? d] (value-for result k) v)))]
|
|
;; remove key k from this dictionary
|
|
[rem (->d ([d dictionary?]
|
|
[k (and/c symbol? (lambda (k) (has? d k)))])
|
|
()
|
|
[result (and/c dictionary? not-has?)]
|
|
#:post-cond
|
|
(= (count d) (+ (count result) 1)))])
|
|
;; end of interface
|