(require-library multi-methods simple-tests) (import multi-methods simple-tests) (define-test (unary?) (check "ARITY 1" (define-multi-method (1+ a)) "INSERT AT END" (multi-method-insert! 1+ (1+-fx? ((a fixnum?)) (fx+ 1 a))) (fx= (1+ 5) 6) (condition-case (= (1+ 5.0) 6.0) ((exn) (print "not a fixnum " 5.0))) (multi-method-insert! 1+ (1+-int? ((a integer?)) (+ 1 a))) (= (1+ 5.0) 6.0) (condition-case (= (1+ 5.5) 6.5) ((exn) (print "not an integer " 5.5))) (multi-method-insert! 1+ (1+-num? ((a number?)) (+ 1 a))) (= (1+ 5.5) 6.5) "INSERT IN THE MIDDLE" (multi-method-insert! 1+ (1+-odd? ((a integer? odd?)) (+ 1 a)) 'integer?) (multi-method? 1+) (not (multi-method? add1)) (fx= (multi-method-arity 1+) 1) (not (multi-method-variadic? 1+)) (equal? (multi-method-keys 1+) '(fixnum? integer?odd? integer? number?)) (equal? (multi-method-tree 1+) '((fixnum? 1+-fx?) (integer?odd? 1+-odd?) (integer? 1+-int?) (number? 1+-num?))) )) (unary?) (define-test (binary?) (check "ARITY 2" (define-multi-method (add a b)) (multi-method? add) (= (multi-method-arity add) 2) (multi-method-empty? add) (not (multi-method-variadic? add)) (multi-method-insert! add (add-num?-num? ((a number?) (b number?)) (+ a b))) (multi-method-insert! add (add-str?-str? ((x string?) (y string?)) (string-append x y))) (multi-method-insert! add (add-fx?-fx? ((a fixnum?) (b fixnum?)) (fx+ a b)) 'number?) (multi-method-insert! add (add-num?-odd? ((a number?) (b integer? odd?)) (+ a b)) 'number? 'number?) (equal? (multi-method-keys add) '(fixnum? number? string?)) (equal? (multi-method-keys add 'number?) '(integer?odd? number?)) (equal? (multi-method-tree add) '((fixnum? ((fixnum? add-fx?-fx?))) (number? ((integer?odd? add-num?-odd?) (number? add-num?-num?))) (string? ((string? add-str?-str?))))) (string=? (add "a" "b") "ab") (fx= (add 1 2) 3) (= (add 1.5 3.0) 4.5) )) (binary?) (define-test (variadic?) (check "ARITY 1" (define-multi-method (mult . as)) (multi-method? mult) (multi-method-variadic? mult) (multi-method-empty? mult) (multi-method-insert! mult (mult-nums? (as number?) (apply * as))) "VARIADIC ARGUMENTS MUSTN'T BE EMPTY" (multi-method-insert! mult (mult-fxs? (as fixnum?) (let loop ((as as) (result 1)) (if (null? as) result (loop (cdr as) (fx* (car as) result))))) 'number?) (fx= (mult 1 2 3 4 5) 120) (= (mult 1.0 2.0 3.0 4.0 5.0) 120.0) (= (mult 1.5) 1.5) "ARITY 2" (define-multi-method (add* a . as)) (multi-method-variadic? add*) (= (multi-method-arity add*) 2) (multi-method-insert! add* (add*-str?-strs? ((a string?) : (as string?)) (apply string-append a as))) (multi-method-insert! add* (add*-fx?-strs? ((a fixnum?) : (as string?)) (apply string-append (->string a) as)) 'string?) (multi-method-insert! add* (add*-num?-nums? ((a number?) : (as number?)) (apply + a as))) (equal? (multi-method-keys add*) '(fixnum? string? number?)) (equal? (multi-method-keys add* 'fixnum?) '(list-of-string?)) (equal? (multi-method-tree add*) '((fixnum? ((list-of-string? add*-fx?-strs?))) (string? ((list-of-string? add*-str?-strs?))) (number? ((list-of-number? add*-num?-nums?))))) (equal? (multi-method-tree add* 'number?) '((list-of-number? add*-num?-nums?))) (string=? (add* "a" "b" "c") "abc") (string=? (add* 1 "b" "c") "1bc") (= (add* 1.0 2.0 3.0) 6.0) (condition-case (add* 1.0) ((exn) (print "variadic arguments mustn't be empty"))) )) (variadic?) (compound-test (MULTI-METHODS) (unary?) (binary?) (variadic?) )