3.4.3 (a) メッセージパッシング
ex. 2.75. make-from-mag-ang をメッセージパッシングで.
ex. 2.75. 実装.
; [ex-2.75.scm]
;
(define (ex-2.75)
(print "(make-from-mag-ang 1 2)")
(print ";==> " (make-from-mag-ang 1 2))
(let
(
(c1 (make-from-mag-ang 1 2))
)
(print "(apply-generic 'real-part c1)")
(print ";==> " (apply-generic 'real-part c1))
(print "(apply-generic 'imag-part c1)")
(print ";==> " (apply-generic 'imag-part c1))
(print "(apply-generic 'magnitude c1)")
(print ";==> " (apply-generic 'magnitude c1))
(print "(apply-generic 'angle c1)")
(print ";==> " (apply-generic 'angle c1))
)
#t)
(load "./sec-3.4.3-a")
; sec 2.4.1 (複素数の表現) を参考に.
(define (make-from-mag-ang r a)
(define (dispatch op)
(cond
((eq? op 'real-part) (* r (cos a)))
((eq? op 'imag-part) (* r (sin a)))
((eq? op 'magnitude) r)
((eq? op 'angle) a)
(else (error "Unknown op: MAKE-FROM-REAL-IMAG" op))))
dispatch
)
ex. 2.75. 実行結果.
gosh> (ex-2.75)
(make-from-mag-ang 1 2)
;==> #<closure (make-from-mag-ang dispatch)>
(apply-generic 'real-part c1)
;==> -0.4161468365471424
(apply-generic 'imag-part c1)
;==> 0.9092974268256817
(apply-generic 'magnitude c1)
;==> 1
(apply-generic 'angle c1)
;==> 2
ex. 2.76. 3 つの戦略の違い.
3 つの戦略:
- 明示的ディスパッチによるジェネリック演算
- データ主導スタイル
- メッセージパッシングスタイル
2 つの変化:
- 新しい型の追加
- 新しい演算の追加
6 つの組み合わせ.
増えた型に対する演算自体の実装追加と, 増えた演算に対する各型での実装追加はいずれの場合でも同様に発生するのでここでは除外とする.
明示的ディスパッチによるジェネリック演算 x 新しい型の追加
既存のディスパッチ関数のうち, 必要な演算に対して分岐を1つずつ追加する.明示的ディスパッチによるジェネリック演算 x 新しい演算の追加
必要な演算に対して新しいディスパッチ関数を追加し, そこに必要な型の数だけ分岐を記述する.データ主導スタイル x 新しい型の追加
新しい型に関して実装したその場所 (登録用固有関数 = モジュール) に, 必要な登録処理を追加する. 既存コードの変更は不要.データ主導スタイル x 新しい演算の追加
新しいディスパッチ関数を追加する. その実装は単純に汎用適用関数を呼び出すのみでよい.メッセージパッシングスタイル x 新しい型の追加
新しい型に関して実装したその場所 (コンストラクタ = モジュール) に, 必要な登録処理を追加する. 既存コードの変更は不要.-
メッセージパッシングスタイル x 新しい演算の追加
新しいディスパッチ関数を追加する. その実装は単純に汎用適用関数を呼び出すのみでよい.
新しい型がよく追加されるシステムでは、どのどの組み立て方が最も適しているだろうか。
どのどの.
加法的に, 既存コードの変更なしに追加ができるデータ主導スタイル若しくはメッセージパッシングスタイルのいずれかであれば同等に適していると思われる.
新しい演算を追加するシステムでは、どれが最も適しているだろうか。
メッセージパッシングスタイルの場合, 演算の実装はコンストラクタと同じ場所に実装する必要がある. このためもし演算の単位で処理をグループ化して記述したい場合にはデータ主導スタイルが適切となる.
特にそのようなグループ化はせず, 型の単位で処理をグループ化して記述するのであればデータ主導スタイルとメッセージパッシングスタイルのいずれかで大きな違いはない.