Add tests for generics.

This commit is contained in:
Vincent St-Amour 2012-05-09 15:31:17 -04:00 committed by Asumu Takikawa
parent c29a65485e
commit 1ec2bc0ea4
4 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,32 @@
#lang racket/base
(require generics racket/dict racket/list)
(define-struct alist (v)
#:property prop:dict
(methods 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))
(define (dict-count dict #:default [x #f])
(or x
(length (remove-duplicates (alist-v dict) #:key car))))))
(module+ test
(require rackunit)
(define d1 '((1 . a) (2 . b)))
(check-true (dict? d1))
(check-eq? (dict-ref d1 1) 'a)
(check-equal? (dict-count (dict-remove d1 2)) 1)
(check-false (dict-mutable? d1))
(check-true (dict-can-remove-keys? d1))
(check-true (dict-can-functional-set? d1)))

View File

@ -0,0 +1,95 @@
#lang racket/base
(require generics
(only-in racket/dict
dict prop:dict
dict?
dict-ref
dict-set!
dict-set
dict-remove!
dict-remove
dict-count)
(only-in racket/list remove-duplicates))
(struct hash-box (key))
(define custom-hash-ref
(case-lambda
[(d k) (hash-ref (custom-hash-table d)
((custom-hash-make-box d) k)
(lambda ()
(raise-mismatch-error
'dict-ref
"no value found for key: "
k)))]
[(d k fail) (hash-ref (custom-hash-table d)
((custom-hash-make-box d) k)
fail)]))
(define (custom-hash-set! d k v)
(hash-set! (custom-hash-table d)
((custom-hash-make-box d) k)
v))
(define (custom-hash-remove! d k)
(hash-remove! (custom-hash-table d)
((custom-hash-make-box d) k)))
(define (custom-hash-count d)
(hash-count (custom-hash-table d)))
(struct custom-hash (table make-box)
#:property prop:dict
(methods dict
(define dict-ref custom-hash-ref)
(define dict-set! custom-hash-set!)
(define (dict-set dict key val)
(error "no functional update"))
(define dict-remove! custom-hash-remove!)
(define (dict-remove dict key)
(error "no functional update"))
(define dict-count custom-hash-count))
#:property prop:equal+hash
(list (lambda (a b recur)
(and (recur (custom-hash-make-box a)
(custom-hash-make-box b))
(recur (custom-hash-table a)
(custom-hash-table b))))
(lambda (a recur) (recur (custom-hash-table a)))
(lambda (a recur) (recur (custom-hash-table a)))))
(define (make-custom-hash =? hash [hash2 (lambda (v) 10001)])
(unless (and (procedure? =?)
(procedure-arity-includes? =? 2))
(raise-type-error 'make-custom-hash "procedure (arity 2)" =?))
(unless (and (procedure? hash)
(procedure-arity-includes? hash 1))
(raise-type-error 'make-custom-hash "procedure (arity 1)" hash))
(unless (and (procedure? hash2)
(procedure-arity-includes? hash2 1))
(raise-type-error 'make-custom-hash "procedure (arity 1)" hash2))
(let ()
(struct box hash-box ()
#:property prop:equal+hash
(list
(lambda (a b recur) (=? (hash-box-key a) (hash-box-key b)))
(lambda (v recur) (hash (hash-box-key v)))
(lambda (v recur) (hash2 (hash-box-key v)))))
(custom-hash (make-hash) box)))
(module+ test
(require rackunit)
;; from the docs
(define h (make-custom-hash (lambda (a b)
(string=? (format "~a" a)
(format "~a" b)))
(lambda (a)
(equal-hash-code
(format "~a" a)))))
(dict-set! h 1 'one)
(check-eq? (dict-ref h "1") 'one))

View File

@ -0,0 +1,59 @@
#lang racket/base
(require generics racket/port)
(define-generics (printable prop:printable printable?)
(gen-print printable [port])
(gen-port-print port printable)
(gen-print* printable [port] #:width width #:height [height]))
(define-struct num (v)
#:property prop:printable
(methods printable
(define/generic super-print gen-print)
(define (gen-print n [port (current-output-port)])
(fprintf port "Num: ~a" (num-v n)))
(define (gen-port-print port n)
(super-print n port))
(define (gen-print* n [port (current-output-port)]
#:width w #:height [h 0])
(fprintf port "Num (~ax~a): ~a" w h (num-v n)))))
(define-struct bool (v)
#:property prop:printable
(methods printable
(define/generic super-print gen-print)
(define (gen-print b [port (current-output-port)])
(fprintf port "Bool: ~a"
(if (bool-v b) "Yes" "No")))
(define (gen-port-print port b)
(super-print b port))
(define (gen-print* b [port (current-output-port)]
#:width w #:height [h 0])
(fprintf port "Bool (~ax~a): ~a" w h
(if (bool-v b) "Yes" "No")))))
(module+ test
(require rackunit)
(define x (make-num 10))
(check-equal? (with-output-to-string (lambda () (gen-print x)))
"Num: 10")
(check-equal? (with-output-to-string
(lambda () (gen-port-print (current-output-port)
x)))
"Num: 10")
(check-equal? (with-output-to-string
(lambda () (gen-print* x #:width 100 #:height 90)))
"Num (100x90): 10")
(define y (make-bool #t))
(check-equal? (with-output-to-string (lambda () (gen-print y)))
"Bool: Yes")
(check-equal? (with-output-to-string
(lambda () (gen-port-print (current-output-port)
y)))
"Bool: Yes")
(check-equal? (with-output-to-string
(lambda () (gen-print* y #:width 100 #:height 90)))
"Bool (100x90): Yes"))

View File

@ -0,0 +1,5 @@
#lang racket/base
(require (submod "custom-hash.rkt" test)
(submod "alist.rkt" test)
(submod "from-docs.rkt" test))