Fixed bugs related to define/generic and to define-generics at top-level.
Added tests using define/generic in both #:defaults and #:fallbacks, both inside modules and at the top level. Changed the implementation of define-generics so that defaults and fallbacks come after method definitions so that define/generic works properly. Changed internal names to be created with format-id and syntax-local-introduce rather than generate-temporaries so that they work at the top level.
This commit is contained in:
parent
30a1c3565d
commit
704857bbfe
|
@ -62,3 +62,56 @@
|
||||||
|
|
||||||
(check-true (to-bool my-a))
|
(check-true (to-bool my-a))
|
||||||
(check-false (to-bool my-b)))
|
(check-false (to-bool my-b)))
|
||||||
|
|
||||||
|
(define-generics nested-stream
|
||||||
|
(nested-stream-first nested-stream)
|
||||||
|
(nested-stream-rest nested-stream)
|
||||||
|
(nested-stream-empty? nested-stream)
|
||||||
|
#:defaults
|
||||||
|
;; list of streams, yield elements of substreams
|
||||||
|
([(lambda (los) (and (list? los) (andmap nested-stream? los)))
|
||||||
|
(define/generic super-first nested-stream-first)
|
||||||
|
(define/generic super-rest nested-stream-rest)
|
||||||
|
(define/generic super-empty? nested-stream-empty?)
|
||||||
|
(define (nested-stream-first los)
|
||||||
|
(when (stream-empty? los)
|
||||||
|
(error 'empty!))
|
||||||
|
(if (super-empty? (first los))
|
||||||
|
(super-first (rest los))
|
||||||
|
(super-first (first los))))
|
||||||
|
(define (nested-stream-rest los)
|
||||||
|
(when (stream-empty? los)
|
||||||
|
(error 'empty!))
|
||||||
|
(if (super-empty? (first los))
|
||||||
|
(super-rest (rest los))
|
||||||
|
(cons (super-rest (first los)) (rest los))))
|
||||||
|
(define (nested-stream-empty? los)
|
||||||
|
(or (empty? los)
|
||||||
|
(and (super-empty? (first los))
|
||||||
|
(super-empty? (rest los)))))]
|
||||||
|
;; base case, flat list
|
||||||
|
[list?
|
||||||
|
(define nested-stream-first first)
|
||||||
|
(define nested-stream-rest rest)
|
||||||
|
(define nested-stream-empty? empty?)]))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(define (nested-stream->list ns)
|
||||||
|
(if (nested-stream-empty? ns)
|
||||||
|
'()
|
||||||
|
(cons (nested-stream-first ns)
|
||||||
|
(nested-stream->list (nested-stream-rest ns)))))
|
||||||
|
|
||||||
|
(define ns1 '())
|
||||||
|
(define ns2 '(() ()))
|
||||||
|
(define ns3 '((1 2 3) (4 5 6)))
|
||||||
|
(define ns4 '((1 2 3) (4 5 6) ()))
|
||||||
|
(define ns5 '((1 (2 (3)) (4 (5 (6))))))
|
||||||
|
(define ns6 '(() (4 (5 (6)))))
|
||||||
|
|
||||||
|
(check-equal? (nested-stream->list ns1) '())
|
||||||
|
(check-equal? (nested-stream->list ns2) '())
|
||||||
|
(check-equal? (nested-stream->list ns3) '(1 2 3 4 5 6))
|
||||||
|
(check-equal? (nested-stream->list ns4) '(1 2 3 4 5 6))
|
||||||
|
(check-equal? (nested-stream->list ns5) '(1 2 3 4 5 6))
|
||||||
|
(check-equal? (nested-stream->list ns6) '(4 5 6)))
|
||||||
|
|
|
@ -84,6 +84,29 @@
|
||||||
(define (make-wrapped n)
|
(define (make-wrapped n)
|
||||||
(wrapped n))
|
(wrapped n))
|
||||||
|
|
||||||
|
(struct generic-wrapped [numeric]
|
||||||
|
#:transparent
|
||||||
|
#:methods gen:numeric
|
||||||
|
[(define/generic numeric-decrement decrement)
|
||||||
|
(define/generic numeric-zero? is-zero?)
|
||||||
|
(define/generic numeric-even? is-even?)
|
||||||
|
(define/generic numeric-odd? is-odd?)
|
||||||
|
(define (decrement n)
|
||||||
|
(generic-wrapped
|
||||||
|
(numeric-decrement
|
||||||
|
(generic-wrapped-numeric n))))
|
||||||
|
(define (is-zero? n)
|
||||||
|
(numeric-zero?
|
||||||
|
(generic-wrapped-numeric n)))
|
||||||
|
(define (is-even? n)
|
||||||
|
(numeric-even?
|
||||||
|
(generic-wrapped-numeric n)))
|
||||||
|
(define (is-odd? n)
|
||||||
|
(numeric-odd?
|
||||||
|
(generic-wrapped-numeric n)))])
|
||||||
|
(define (make-generic-wrapped n)
|
||||||
|
(generic-wrapped (make-peano n)))
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(require rackunit rackunit/text-ui)
|
(require rackunit rackunit/text-ui)
|
||||||
|
|
||||||
|
@ -106,4 +129,5 @@
|
||||||
(tests "peano" make-peano)
|
(tests "peano" make-peano)
|
||||||
(tests "binary" make-binary)
|
(tests "binary" make-binary)
|
||||||
(tests "parity" make-parity)
|
(tests "parity" make-parity)
|
||||||
(tests "wrapped" make-wrapped))))
|
(tests "wrapped" make-wrapped)
|
||||||
|
(tests "generic-wrapped" make-generic-wrapped))))
|
||||||
|
|
|
@ -10,7 +10,14 @@
|
||||||
(check-not-exn
|
(check-not-exn
|
||||||
(λ ()
|
(λ ()
|
||||||
(eval '(require racket/generic) ns)
|
(eval '(require racket/generic) ns)
|
||||||
(eval '(define-generics foobar [foo foobar a1]) ns)
|
(eval '(define-generics foobar [foo foobar a1] [bar foobar a1]
|
||||||
|
#:defaults ([keyword?
|
||||||
|
(define/generic gbar bar)
|
||||||
|
(define (bar foobar a1) (gbar a1 '#:dummy))])
|
||||||
|
#:fallbacks [(define/generic gfoo foo)
|
||||||
|
(define (foo foobar a1) 'foo)
|
||||||
|
(define (bar foobar a1) (gfoo a1 foobar))])
|
||||||
|
ns)
|
||||||
(eval '(struct inst ()
|
(eval '(struct inst ()
|
||||||
;; make sure `gen:foobar` doesn't cause an
|
;; make sure `gen:foobar` doesn't cause an
|
||||||
;; error here
|
;; error here
|
||||||
|
|
|
@ -53,12 +53,21 @@
|
||||||
(define/with-syntax [method-index ...] method-indices)
|
(define/with-syntax [method-index ...] method-indices)
|
||||||
(define/with-syntax contract-str
|
(define/with-syntax contract-str
|
||||||
(format "~s" (syntax-e #'predicate-name)))
|
(format "~s" (syntax-e #'predicate-name)))
|
||||||
(define/with-syntax (default-pred-name ...)
|
(define/with-syntax ([default-pred-name default-impl-name] ...)
|
||||||
(generate-temporaries #'(default-pred ...)))
|
(for/list ([pred-stx (in-list (syntax->list #'(default-pred ...)))]
|
||||||
(define/with-syntax (default-impl-name ...)
|
[i (in-naturals 0)])
|
||||||
(generate-temporaries #'(default-pred ...)))
|
(list (format-id (syntax-local-introduce #'self-name)
|
||||||
|
"~a-default-pred~a"
|
||||||
|
#'self-name
|
||||||
|
i)
|
||||||
|
(format-id (syntax-local-introduce #'self-name)
|
||||||
|
"~a-default-impl~a"
|
||||||
|
#'self-name
|
||||||
|
i))))
|
||||||
(define/with-syntax fallback-name
|
(define/with-syntax fallback-name
|
||||||
(generate-temporary #'self-name))
|
(format-id (syntax-local-introduce #'self-name)
|
||||||
|
"~a-fallback"
|
||||||
|
#'self-name))
|
||||||
#'(begin
|
#'(begin
|
||||||
(define-syntax generic-name
|
(define-syntax generic-name
|
||||||
(make-generic-info (quote-syntax property-name)
|
(make-generic-info (quote-syntax property-name)
|
||||||
|
@ -88,11 +97,6 @@
|
||||||
[else (raise-argument-error who 'contract-str self-name)]))
|
[else (raise-argument-error who 'contract-str self-name)]))
|
||||||
(define-values (default-pred-name ...)
|
(define-values (default-pred-name ...)
|
||||||
(values default-pred ...))
|
(values default-pred ...))
|
||||||
(define default-impl-name
|
|
||||||
(generic-method-table generic-name default-defn ...))
|
|
||||||
...
|
|
||||||
(define fallback-name
|
|
||||||
(generic-method-table generic-name fallback-defn ...))
|
|
||||||
(define-generic-support supported-name
|
(define-generic-support supported-name
|
||||||
self-name
|
self-name
|
||||||
[method-name ...]
|
[method-name ...]
|
||||||
|
@ -105,7 +109,12 @@
|
||||||
(or (vector-ref (table-name self-name 'method-name) 'method-index)
|
(or (vector-ref (table-name self-name 'method-name) 'method-index)
|
||||||
(vector-ref fallback-name 'method-index))
|
(vector-ref fallback-name 'method-index))
|
||||||
original)
|
original)
|
||||||
...))]))
|
...
|
||||||
|
(define default-impl-name
|
||||||
|
(generic-method-table generic-name default-defn ...))
|
||||||
|
...
|
||||||
|
(define fallback-name
|
||||||
|
(generic-method-table generic-name fallback-defn ...))))]))
|
||||||
|
|
||||||
(define-syntax (define-primitive-generics stx)
|
(define-syntax (define-primitive-generics stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user