racket/collects/tests/generic/contract.rkt
Asumu Takikawa 552d6de953 racket/generics: add contract combinator
The generics library now generates a `name/c` macro
for a generic interface `name`. The combinator can be
used to contract instances (or constructors) of a
generic interface across standard contract boundaries.
2012-06-25 20:33:48 -04:00

54 lines
1.5 KiB
Racket

#lang racket/load
(module a racket/base
(require racket/generic)
(define-generics simple-dict
(dict-ref simple-dict key [default])
(dict-set simple-dict key val)
(dict-remove simple-dict key))
(provide dict-ref
dict-set
dict-remove
gen:simple-dict
simple-dict?
simple-dict/c))
(module b racket/base
(require 'a racket/contract)
;; same as in "alist.rkt"
(define-struct alist (v)
#:methods gen:simple-dict
[(define (dict-ref dict key
[default (lambda () (error "key not found" key))])
(cond [(assoc key (alist-v dict)) => cdr]
[else (if (procedure? default) (default) default)]))
(define (dict-set dict key val)
(alist (cons (cons key val) (alist-v dict))))
(define (dict-remove dict key)
(define al (alist-v dict))
(remove* (assoc key al) al))])
(provide/contract
[make-alist
(-> list?
(simple-dict/c
[dict-ref (->* (simple-dict? symbol?) (any/c) integer?)]
[dict-set (-> simple-dict? symbol? integer? simple-dict?)]
[dict-remove (-> simple-dict? symbol? simple-dict?)]))]))
(module c racket/base
(require 'a 'b rackunit)
(define dict (make-alist '((a . 5) (b . 10))))
(check-equal? (dict-ref dict 'a) 5)
(check-equal? (dict-ref dict 'b) 10)
(check-exn exn:fail:contract?
(λ () (dict-set dict 'a "bad")))
(check-exn exn:fail:contract?
(λ () (dict-set dict "bad" 5))))
(require 'c)