SICP 読書ノート#19 - 2.4 抽象データの多重表現 (pp.99-105)
「§2.4 抽象データの多重表現」から。
はじめに
§2.4の最後の問題2.76で総括するが、抽象データの汎用演算の構築には3つの戦略がある。
- 明白な振り分けを持つ汎用演算 (strategies—generic operations with explicit dispatch)
- データ主導流 (data-directed style)
- メッセージパッシング流 (message-passing-style)
この3つの戦略のメリット・デメリットを理解し使いこなせるようになることがこの章の目的かな思われる。
複素数の表現
複素数データの表現には直交座標形式と極座標形式がある。高校数学の内容なのでここは理解できてるはず。
タグ付きデータ
複素数データが直交座標形式か極座標形式かを明確にするために、型タグ(type tag)を導入する。
コンストラクタは、コンテンツとなる複素数データにタグ付けを行う手続きとする。
(define (make-from-real-imag-rectangular x y) (attach-tag 'rectangular (cons x y))) (define (make-from-mag-ang-rectangular r a) (attach-tag 'rectangular (cons (* r (cos a)) (* r (sin a))))) (define (make-from-real-imag-polar x y) (attach-tag 'polar (cons (sqrt (+ (square x) (square y))) (atan y x)))) (define (make-from-mag-ang-polar r a) (attach-tag 'polar (cons r a)))
複素数データにタグ付けを行うattach-tag、タグ付けされたデータからタグまたはコンテンツを剥がすtype-tag、contentsは、それぞれ以下のように実装される。
(define (attach-tag type-tag contents) (cons type-tag contents)) (define (type-tag datum) (if (pair? datum) (car datum) (error "Bad tagged datum -- TYPE-TAG" datum))) (define (contents datum) (if (pair? datum) (cdr datum) (error "Bad tagged datum -- CONTENTS" datum)))
複素数データのコンテンツの実部、虚部、絶対値、偏角のアクセサも、直交座標系式/極座標形式でそれぞれ実装する。
(define (real-part-rectangular z) (car z)) (define (real-part-polar z) (* (magnitude-polar z) (cos (angle-polar z)))) (define (imag-part-rectangular z) (cdr z)) (define (imag-part-polar z) (* (magnitude-polar z) (sin (angle-polar z)))) ...
明白な振り分けを持つ汎用演算 (strategies—generic operations with explicit dispatch) では、型タグを参照して、それぞれの型のアクセサにディスパッチする。
(define (real-part z) (cond ((rectangular? z) (real-part-rectangular (contents z))) ((polar? z) (real-part-polar (contents z))) (else (error "Unknown type -- REAL-PART " z)))) ...
いかにももっと抽象化できそうな雰囲気を漂わせているが、その手法のひとつとして次節でデータ主導プログラミングが登場。
というわけで、次回は「§2.4.3 データ主導プログラミングと加法性」から。