sicp每日一題[2.82]

再思即可發表於2024-11-19

Exercise 2.82

Show how to generalize apply-generic to handle coercion in the general case of multiple arguments. One strategy is to attempt to coerce all the arguments to the type of the first argument,
then to the type of the second argument, and so on. Give an example of a situation where this strategy (and likewise the two-argument version given above) is not sufficiently general.
(Hint: Consider the case where there are some suitable mixed-type operations present in the table that will not be tried.)


這道題還是挺難的,題目的提示是透過一個雙迴圈來依次進行型別轉換,我參考別人的程式碼修改了很久最後才能跑通,用下面的程式碼替換上一題的 apply-generic 過程,可以驗證是否能用。

(define (apply-generic op . args) 
  (define (no-method type-tags) 
    (error "No method for these types" 
           (list op type-tags)))
  
  (define (type-tags args) 
         (map type-tag args))

  ; 對每一個引數嘗試進行強制型別轉換
  (define (try-coerce-to target)
    (map (lambda (origin)
           (if (eq? (type-tag origin) (type-tag target))
               (lambda (x) x)   ; 如果型別一致,不進行轉換
               (let ((coercor (get-coercion (type-tag origin) (type-tag target)))) 
                 (if coercor 
                     (coercor origin) 
                     origin)))) 
           args))
  
  (define (iterate next) 
    (if (null? next)
        (no-method (type-tags args)) 
        (let ((coerced (try-coerce-to (car next)))) 
          (let ((proc (get op (type-tags coerced)))) 
            (if proc 
                (apply proc (map contents coerced)) 
                (iterate (cdr next))))))) 
  
  (let ((proc (get op (type-tags args)))) 
    (if proc 
        (apply proc (map contents args)) 
        (iterate args))))

相關文章