SICPを読む(87) 問題 2.75 - 問題 2.76 メッセージパッシング
もうひとつのデータ主導実装。メッセージパッシングについて学ぶ。
メッセージパッシング
前回は、環境がメソッドを知っていた。「賢明な手続き」という。主にC++/Javaみたいなコンパイル型言語で使う方法かな。
今回のは、オブジェクトがメソッドを知ってる。「賢明なデータオブジェクト」という。つまり、ミニ環境を持った手続き(クロージャ)を返す。
Schemeなら、メッセージパッシングの方が断然スマートな解決法だと思う。
Wikipediaを見ると、OSでもメッセージパッシングが使われてる事がわかる。
メッセージ (コンピュータ) - Wikipedia
おぉ、システムコールはメッセージパッシングだ。イベントドリブンもメッセージパッシングだ。通信には非常に有用な手法なようだ。
問題 2.75
make-from-mag-angをメッセージパッシング流に直す問題。
(define (make-from-mag-ang x y) (lambda (op) (cond ((eq? op 'real-part) (* x (cos y))) ((eq? op 'imag-part) (* x (sin y))) ((eq? op 'magnitude) x) ((eq? op 'angle) y) (else (error "Unknown op" op))))) (define z (make-from-mag-ang 1.0 (/ pi 6))) ; #<procedure> (z 'real-part) ; 0.8660254037844387 (z 'imag-part) ; 0.49999999999999994
zオブジェクトに対して、メッセージを送ってるんだ。ふむふむ。ある意味通信してるように見える。オブジェクトに対するメッセージという発想は無かった。メソッドというより、メッセージだ。
なんか凄く新しいオブジェクト指向感があるな。メッセージパッシングかふむふむ。
で、apply-genericを通すと、
(define (apply-generic op arg) (arg op)) (define (real-part z) (apply-generic 'real-part z)) (real-part z) ; 0.8660254037844387
Scheme的にはこっちの方が自然かな。
問題 2.76
明白な振り分け、データ主導、メッセージパッシングについて学んだ。
新しい型、演算がどんどん追加されるときどれが適切なのかという問題。
新しい型の追加について考えてみる
明白な振り分け
- 全ての演算に手を加える必要がある。
データ主導
- 型を増やすだけ
メッセージパッシング
- 型を増やすだけ
型を増やしても、中央システムに手を加える必要が無い。というのがデータ主導、メッセージパッシングの大きな特徴。
まとめると
- 型が少ない場合は、明白な振り分けが有用。
- データ主導は、インターフェイスがあるので、確実な運用をすることが出来る。非常に面倒。
- メッセージパッシングは宇宙のように色々出来るけど、自由過ぎる。
- 型がどんどん増える場合は、データ主導、メッセージパッシング。
- 演算がどんどん増える増える場合は、明白な振り分け。インターフェイスを持たないメッセージパッシング。
- 型がどんどん増えて、演算がどんどん増えたら、インターフェイスを持ったデータ主導。メッセージパッシングでの手法は別にありそうな予感(多重継承とか)。
どれが適切かという問はよくわからない。「わかってたらSICPを読まない」というのが僕の答です。