Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -0,0 +1,86 @@
|
|||
#lang racket
|
||||
(module+ test (require tests/eli-tester))
|
||||
|
||||
;; This is all that an object should need to properly implement.
|
||||
(define edible<%>
|
||||
(interface () [eat (->m void?)]))
|
||||
|
||||
(define (generic-container<%> containee/c)
|
||||
(interface ()
|
||||
[contents (->m (listof containee/c))]
|
||||
[insert (->m containee/c void?)]
|
||||
[remove-at (->m exact-nonnegative-integer? containee/c)]
|
||||
[count (->m exact-nonnegative-integer?)]))
|
||||
|
||||
(define ((generic-box-mixin containee/c) %)
|
||||
(->i ([containee/c contract?])
|
||||
(rv (containee/c) (implementation?/c (generic-container<%> containee/c))))
|
||||
(class* % ((generic-container<%> containee/c))
|
||||
(super-new)
|
||||
(define l empty)
|
||||
(define/public (contents) l)
|
||||
(define/public (insert o) (set! l (cons o l)))
|
||||
(define/public (remove-at i)
|
||||
(begin0 (list-ref l i)
|
||||
(append (take l i) (drop l (add1 i)))))
|
||||
(define/public (count) (length l))))
|
||||
|
||||
;; As I understand it, a "Food Box" from the task is still a generic... i.e.
|
||||
;; you will specify it down ;; to an "apple-box%" so: food-box%-generic is still
|
||||
;; generic. food-box% will take any kind of food.
|
||||
(define/contract (food-box-mixin T%)
|
||||
(-> (or/c (λ (i) (eq? edible<%> i)) (implementation?/c edible<%>))
|
||||
(make-mixin-contract))
|
||||
(generic-box-mixin (and/c (is-a?/c edible<%>) (is-a?/c T%))))
|
||||
|
||||
(module+ test
|
||||
|
||||
(define integer-box% ((generic-box-mixin integer?) object%))
|
||||
(define integer-box (new integer-box%))
|
||||
|
||||
(define apple%
|
||||
(class* object% (edible<%>)
|
||||
(super-new)
|
||||
(define/public (eat)
|
||||
(displayln "nom!"))))
|
||||
|
||||
(define banana%
|
||||
(class* object% (edible<%>)
|
||||
(super-new)
|
||||
(define/public (eat)
|
||||
(displayln "peel.. peel... nom... nom!"))))
|
||||
|
||||
(define semolina%
|
||||
(class* object% () ; <-- empty interfaces clause
|
||||
(super-new)
|
||||
;; you can call eat on it... but it's not explicitly (or even vaguely)
|
||||
;; edible<%>
|
||||
(define/public (eat) (displayln "blech!"))))
|
||||
|
||||
;; this will take any object that is edible<%> and edible<%> (therefore all
|
||||
;; edible<%> objects)
|
||||
(define any-food-box (new ((food-box-mixin edible<%>) object%)))
|
||||
|
||||
;; this will take any object that is edible and an apple<%>
|
||||
;; (therefore only apple<%>s)
|
||||
(define apple-food-box (new ((food-box-mixin apple%) object%)))
|
||||
|
||||
(test
|
||||
;; Test generic boxes
|
||||
(send integer-box insert 22)
|
||||
(send integer-box insert "a string") =error> exn:fail:contract?
|
||||
|
||||
;; Test the food box that takes any edible<%>
|
||||
(send any-food-box insert (new apple%))
|
||||
(send any-food-box insert (new banana%))
|
||||
(send any-food-box insert (new semolina%)) =error> exn:fail:contract?
|
||||
|
||||
;; Test the food box that takes any apple%
|
||||
(send apple-food-box insert (new apple%))
|
||||
(send apple-food-box insert (new banana%)) =error> exn:fail:contract?
|
||||
(send apple-food-box insert (new semolina%)) =error> exn:fail:contract?
|
||||
(send apple-food-box count) => 1
|
||||
|
||||
;; Show that you cannot make a food-box from the non-edible<%> semolina cannot
|
||||
(implementation? semolina% edible<%>) => #f
|
||||
(new ((food-box-mixin semolina%) object%)) =error> exn:fail:contract?))
|
||||
Loading…
Add table
Add a link
Reference in a new issue