146 lines
4.1 KiB
Racket
146 lines
4.1 KiB
Racket
#lang racket
|
|
(require unstable/generics
|
|
tests/eli-tester)
|
|
|
|
(define (massq idx l)
|
|
(match l
|
|
[(mcons (and v (mcons (? (curry equal? idx)) _)) _)
|
|
v]
|
|
[(mcons _ rst)
|
|
(massq idx rst)]
|
|
[null
|
|
#f]))
|
|
|
|
(test
|
|
(local
|
|
[(define-generics (lots prop:lots lots?)
|
|
(f #:foo foo lots zog [def]))
|
|
|
|
(define-struct ex ()
|
|
#:property prop:lots
|
|
(define-methods lots
|
|
(define (f #:foo foo lots zog [def #t])
|
|
1)))]
|
|
(test
|
|
(f #:foo 3 (make-ex) 2) => 1
|
|
(f (make-ex) #:foo 3 2) => 1
|
|
(f (make-ex) 2 #:foo 3) => 1))
|
|
|
|
(local
|
|
[(define-generics (lots prop:lots lots?)
|
|
(f #:foo foo lots zog #:def [def]))
|
|
|
|
(define-struct ex ()
|
|
#:property prop:lots
|
|
(define-methods lots
|
|
(define (f #:foo foo lots zog #:def [def #t])
|
|
1)))]
|
|
(test
|
|
(f #:foo 3 (make-ex) 2) => 1
|
|
(f (make-ex) 4 #:foo 3 #:def 2) => 1
|
|
(f (make-ex) 3 #:foo 1) => 1))
|
|
|
|
(local
|
|
[(define-generics (lots prop:lots lots?)
|
|
(f lots idx val))
|
|
|
|
(define-struct ex ()
|
|
#:property prop:lots
|
|
(define-methods lots
|
|
(define/generic gen:f f)
|
|
(define (f lots idx val)
|
|
(if (zero? idx)
|
|
val
|
|
(gen:f lots (sub1 idx) (* 2 val))))))]
|
|
(test
|
|
(f (make-ex) 4 1) => (expt 2 4)))
|
|
|
|
(local
|
|
[(generics table
|
|
(get table idx [default])
|
|
(weird-get idx table)
|
|
(put! table idx new))
|
|
|
|
(define-struct alist ([l #:mutable])
|
|
#:property prop:table
|
|
(define-methods table
|
|
(define (get table idx [default #f])
|
|
(cond [(massq idx (alist-l table)) => mcdr]
|
|
[else default]))
|
|
(define (weird-get idx table)
|
|
(get table idx))
|
|
(define (put! table idx new)
|
|
(let* ([l (alist-l table)]
|
|
[prev (massq idx l)])
|
|
(if prev
|
|
(set-mcar! prev new)
|
|
(set-alist-l! table (mcons (mcons idx new) (alist-l table))))))))]
|
|
|
|
(test
|
|
(make-alist empty)
|
|
|
|
(get (make-alist empty) 'foo) => #f
|
|
|
|
(local [(define t (make-alist empty))]
|
|
(put! t 'foo 1)
|
|
(get t 'foo))
|
|
=>
|
|
1
|
|
|
|
(weird-get 'foo (make-alist empty)) => #f
|
|
|
|
(local [(define t (make-alist empty))]
|
|
(put! t 'foo 1)
|
|
(weird-get 'foo t))
|
|
=>
|
|
1))
|
|
|
|
(test
|
|
(generics table
|
|
(get idx [default]))
|
|
=error>
|
|
"No required by-position generic argument"
|
|
|
|
(generics table
|
|
(get idx [table] [default]))
|
|
=error>
|
|
"No required by-position generic argument")
|
|
|
|
|
|
(local [(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
|
|
(define-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
|
|
(define-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")))))
|
|
|
|
(define x (make-num 10))
|
|
(define y (make-bool #t))]
|
|
(test
|
|
(gen-print x)
|
|
(gen-port-print (current-output-port) x)
|
|
(gen-print* x #:width 100 #:height 90)
|
|
|
|
(gen-print y)
|
|
(gen-port-print (current-output-port) y)
|
|
(gen-print* y #:width 100 #:height 90)))) |