my attempt to do the exercises in sicp.

Saturday, August 9, 2008

sicp exercise 2.82

;; 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.)

(define (apply-generic op . args)
  (define (find-coercions atype other-types)
    (cond ((null? other-types) (list))
          ((eq? atype (car other-types)) (lambda(x)(x)))
          (else (let ((coerce-func (get-coercion atype (car other-types))))
                  (if (null? coerce-func) (list)
                      (cons coerce-func
                            (find-coercions atype (cdr other-types))))))))
  (let ((type-tags (map type args)))
    (let ((proc (get op type-tags)))
        (define (iter remaining-types)
          (if (null? remaining-types) (error "no more types")
            (let ((coerced-type (car remianing-types)))
              (let ((coerced-funcs (find-coercions coerced-type type-tags))
                    (length-types (length type-tags)))
                (if (not (= (length coerced-funcs) length-types)) (iter (cdr remaining-types))
                    (let ((new-types (map (lambda(x)(coerced-type)) type-tags)))
                      (let ((new-proc (get op new-types)))
                        (if new-proc (apply op (map contents (map-multi coerced-funcs args)))
                                     (iter (cdr remaining-types))))))))))
      (if proc (apply op (map contents args))
          (iter type-tags)))))

No comments: