2008. 8. 5.

연습문제 2.80

(define (=zero? v) (apply-generic '=zero? v))

(put '=zero? 'scheme-number
     (lambda (n) (= n 0)))

(define (=zero?rat r1)
  (and (= (denom r1) 0)
       (= (numer r1) 0)))

(put '=zero? 'rational
     (lambda (r) (=zero?rat r)))

(define (=zero?complex c1)
  (and (= (real-part c1) 0)
       (= (imag-part c1) 0)))

(put '=zero? 'complex
     (lambda (c) (=zero?complex c)))

연습문제 2.80

(define (=zero? v) (apply-generic '=zero? v))

(put '=zero? 'scheme-number
     (lambda (n) (= n 0)))

(define (=zero?rat r1)
  (and (= (denom r1) 0)
       (= (numer r1) 0)))

(put '=zero? 'rational
     (lambda (r) (=zero?rat r)))

(define (=zero?complex c1)
  (and (= (real-part c1) 0)
       (= (imag-part c1) 0)))

(put '=zero? 'complex
     (lambda (c) (=zero?complex c)))

연습문제 2.79

(define (equ-complex c1 c2)
  (and (= (real-part c1) (real-part c2))
       (= (imag-part c1) (imag-part c2))))

(put 'equ? '(complex complex)
     (lambda (z1 z2) (equ-complex z1 z2)))

(define (equ-rat r1 r2)
  (and (= (denom r1) (denom r2))
       (= (number r1) (number r2))))

(put 'equ? '(rational rational)
     (lambda (r1 r2) (equ-rat r1 r2)))

(put 'equ? '(scheme-number scheme-number)
     (lambda (n1 n2) (= n1 n2)))

(define (equ? x y) (apply-generic 'equ? x y))

연습문제 2.79

(define (equ-complex c1 c2)
  (and (= (real-part c1) (real-part c2))
       (= (imag-part c1) (imag-part c2))))

(put 'equ? '(complex complex)
     (lambda (z1 z2) (equ-complex z1 z2)))

(define (equ-rat r1 r2)
  (and (= (denom r1) (denom r2))
       (= (number r1) (number r2))))

(put 'equ? '(rational rational)
     (lambda (r1 r2) (equ-rat r1 r2)))

(put 'equ? '(scheme-number scheme-number)
     (lambda (n1 n2) (= n1 n2)))

(define (equ? x y) (apply-generic 'equ? x y))

연습문제 2.78

(define (type-tag datum)
  (cond ((number? datum) 'scheme-number)
        ((pair? datum) (car datum))
        (else (error "Bad tagged datum -- TYPE-TAG" datum))))

(define (attach-tag type-tag contents)
  (cond ((number? contents) contents)
        (else (cons type-tag contents))))

(define (contents datum)
  (cond ((numer? datum) datum)
        ((pair? datum) (cdr datum))
        (else (error "Bad tagged datum -- CONTENTS" datum))))

연습문제 2.78

(define (type-tag datum)
  (cond ((number? datum) 'scheme-number)
        ((pair? datum) (car datum))
        (else (error "Bad tagged datum -- TYPE-TAG" datum))))

(define (attach-tag type-tag contents)
  (cond ((number? contents) contents)
        (else (cons type-tag contents))))

(define (contents datum)
  (cond ((numer? datum) datum)
        ((pair? datum) (cdr datum))
        (else (error "Bad tagged datum -- CONTENTS" datum))))

연습문제 2.77

그림 2.24는 Scheme 문으로는 다음과 같다.

(cons 'complex (cons 'rectangular (cons 3 4)))
-> (complex rectangular 3 . 4)

Louis Reasoner가 원한 (magnitude z)를 얻기 위해서는 실제로 다음과 같은 호출이 있어야한다.

(apply-generic 'magnitude z)

이전 챕터에서 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))
          (error
            "No method for these types -- APPLY-GENERIC"
            (list op type-tags))))))

따라서 해당하는 형의 태그내에서 실제로 함수를 발견하지못했기때문에 에러가 발생한다.
apply-generic은 먼저 args의 형을 가져오고 다음에 해당하는 태그에 맞는 함수를 가져온다. 따라서 'complex에 대해 한번, 'magnitude에 대해 한번 수행한다.