51 lines
2 KiB
Text
51 lines
2 KiB
Text
a) This is not going to work, it will simply coerce one of the complex numbers
|
|
into a complex number, then call the 'exp procedure generically for two
|
|
complex numbers, and will then loop infinitely.
|
|
|
|
b) He is mostly wrong, the apply-generic procedure will error out if the types
|
|
are the same and there is no procedure for them. But this is what we'd expect.
|
|
It just means there is no procedure for these types.
|
|
|
|
Maybe this is what we want, but we may actually want the type of both to be
|
|
raised when we attempt this procedure.
|
|
|
|
That being said, the example presented:
|
|
```
|
|
(define (exp x y) (apply-generic 'exp x y))
|
|
;; following added to Scheme-number package
|
|
(put 'exp '(scheme-number scheme-number)
|
|
(lambda (x y) (tag (expt x y))))
|
|
; using primitive expt
|
|
(exp complex1 complex2)
|
|
```
|
|
would not work, *even* if we did that, because complex numbers are supertypes
|
|
of scheme numbers, and couldn't be simplified.
|
|
|
|
c) Okay, but it's just going to error out in the exact same way, just in a
|
|
different place.
|
|
|
|
```
|
|
(define (apply-generic op . args)
|
|
(let ((type-tags (map type-tag args)))
|
|
(let ((proc (get op type-tags)))
|
|
(if proc
|
|
(apply proc (map contents args))
|
|
(if (= (length args) 2)
|
|
(let ((type1 (car type-tags))
|
|
(type2 (cadr type-tags))
|
|
(a1 (car args))
|
|
(a2 (cadr args)))
|
|
(if (eq? type1 type2)
|
|
(error "No method for these types"
|
|
(list op type-tags))
|
|
(let ((t1->t2 (get-coercion type1 type2))
|
|
(t2->t1 (get-coercion type2 type1)))
|
|
(cond (t1->t2
|
|
(apply-generic op (t1->t2 a1) a2))
|
|
(t2->t1
|
|
(apply-generic op a1 (t2->t1 a2)))
|
|
(else (error "No method for these types"
|
|
(list op type-tags)))))))
|
|
(error "No method for these types"
|
|
(list op type-tags)))))))
|
|
```
|