問題2-77

「2-5 汎用演算のシステム」の節に入りました。ここから先の問題に取り組むためには、本書に掲載されているコードを書かなければならず、それに結構時間がかかってしまいました。しかし、書いてみることで、今までの自分の理解不足を補えたという利点もありました。
問題2-77は、複素数パッケージを定義の足りない部分を補うという問題です。(magnitude z)がどのように評価されていくのかを見ていきます。まずは、complex-packageを使って、ある複素数の値を定義すると、どのような構造になっているのかを調べます。

(install-complex-package)  ;=>done

(define test
  (make-complex-from-mag-ang 3 4))

(car test)  ;=>complex
(cadr test)  ;=>polar
(cddr test)  ;=>(3 . 4)

確かに、p113の図2.24のような構造になっています。そのため、Alyssa P. Hackerの提言を受け入れる前の状態で、(magnitude z)を行なうと、apply-genericを通過するときに、'magnitudeと'complexでgetしてしまいます。しかし、この組み合わせは存在していません。存在するのは、'magnitudeと'rectangular/'polarの組み合わせのみです。そのため、'complexタグを剥がして、'rectangular/'polarと'magnitudeでapply-genericを通過させる必要があります。
そこで、complex-packageの中に、(put 'magnitude '(complex) magnitude)を追加してやります。すると、最初のapply-genericのget時に、この組み合わせを見つけることができます。同時に、渡された値のcontentsにmagnitudeがapplyされます。この時のcontentsは、polarタグのついた複素数の実データですので、(define (magnitude z) (apply-generic 'magnitude z))が適用された時にzのタグであるpolarでgetが行なわれ、これでやっと実データを拾えることになります。
文章で書くとわかりにくくなってしまいましたが、apply-genericのことを昨日まで全く理解していなかったことに気づけたことは大きな発見だったような気がしています。