
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.
54 lines
1.5 KiB
Racket
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)
|