2.5.1 汎用算術演算

みんな大好き汎用算術演算!

問題 2.77

これがどうして働くか。

complex は構築子で、
'((complex rectangular x . y)) もしくは
'((complex polar r . a)) のようにタグを 2 レベル分持つように
設計されている。複合タグとでも呼べばいいのかな。

complex パッケージに以下のとおり put を追加すると

  (put 'real-part '(complex) real-part)
  (put 'imag-part '(complex) imag-part)
  (put 'magnitude '(complex) magnitude)
  (put 'angle '(complex) angle)

次のタグ(rectangular もしくは polar) に対して
同じ手続きを評価する動きになる。

トレースせよ。

gosh> (define z (make-complex-from-real-imag 3 4))
gosh> (magnitude z)

(magnitude z)
==> (magnitude '((complex rectangular 3 . 4)))

・apply-generic 一回目
op='magnitude args='((complex rectangular 3 . 4))

complex に (put 'magnitude '(complex) magnitude) を追加定義したので、
proc = magnitude で apply proc (map contents args) を評価する。

・apply-generic 二回目
op=magnitude args='((rectangular 3 . 4))

rectangular で (put 'magnitude '(rectangular) magnitude) として
手続きを put しているので同パッケージの以下 magnitude を評価する。

  (define (magnitude z)
    (sqrt (+ (square (real-part z))
             (square (imag-part z)))))

(real-part z) = 3, (imag-part z) = 4 なので、
(sqrt (+ 3^2 4^2)) = 5 となるので、
結果として 5 を返す。

問題 2.78

問題にあるように attach-tag, type-tag, contents だけ修正します。

(define (attach-tag type-tag contents)
  (if (eq? type-tag 'scheme-number)
      contents
      (cons type-tag contents)))

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

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

手続き内に「'scheme-number」があるのが個人的に微妙な気がします。

gosh> (mul (add 1 2) (add 3 4))
21

こんな風に内部の数字型がそのまま使えるようになります。