Practice 2.81
(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)))
(let ((t1->t2 (get-coercion type1 type2))
(t2->t1 (get-coercion type2 typw1)))
(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)))))))
when invoking (apply-generic ‘exp x y), both x y are scheme-number, let proc equal (get ‘exp ‘(scheme-number scheme-number)), it will work well, if invoking (apply-generic ‘exp x y), both x and y are complex, (get ‘exp ‘(complex complex)) is not in table,it will coerce type1 to type2 or type2 to type1, since both type1 and type2 are complex, it will call (apply-generic op a1 a2). That is just the start status (apply-generic op.args). So it’s a infinite loop. It will not get the correct anwser.
Modified apply-generic
(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 (not (eq? type1 type2))
(let ((t1->t2 (get-coercion type1 type2))
(t2->t1 (get-coercion type2 typw1)))
(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))))
(error "No method for these types"
(list op type-tags)))))))