;; A Collection is a (Msg -> Procedure) ;; where Msg is one of: ;; - 'is-empty => (Self -> Boolean) ;; - 'add-elem => (Self * Value -> Collection) ;; - 'some-elem => (Self -> (list Value Collection)) ;; - 'add-all-elems => (Self * Collection -> Collection) ;; - 'to-list => (Self -> Listof[Value]) ;; In this file, we only give a partial definition of Collection, ;; where the only concrete method implementation is for add-all-elems ;; (because that can be defined in terms of the other Collection ;; methods). It will be the responsibilty of our subclasses to ;; supply the remaining three method implementations. (define base-collection 'abstract-constructor-defined-below) (define isEmpty (lambda (c) ((c 'is-empty) c))) (define addElem (lambda (c v) ((c 'add-elem) c v))) (define anyElem (lambda (c) ((c 'some-elem) c))) (define addAll (lambda (c c2) ((c 'add-all-elems) c c2))) (define toList (lambda (c) ((c 'to-list) c))) (letrec ((concrete->object ;; -> Collection (lambda () (lambda (sym) (cond ((eq? sym 'add-all-elems) ;; this is one concrete method (lambda (self other-collection) (if (isEmpty other-collection) self (let* ((val-and-other-rest (anyElem other-collection)) (val (list-ref val-and-other-rest 0)) (other-rest (list-ref val-and-other-rest 1))) (addAll (addElem self val) other-rest))))) ((eq? sym 'to-list) ;; this is another concrete method (lambda (self) (if (isEmpty self) '() (let* ((val-and-other-rest (anyElem self)) (val (list-ref val-and-other-rest 0)) (other-rest (list-ref val-and-other-rest 1))) (cons val (toList other-rest)))))) ;; The methods is-empty, add-elem, and some-elem are ;; all *abstract*; it is the duty of our concrete ;; subclass to provide their implementation. (else (error 'unimplemented-message "~a" sym))))))) (set! base-collection (lambda () (concrete->object))))