SICP §2.4(データ主導プログラミングと加法性 その4[メッセージパッシング])
SCIPに復帰〜♪
このエントリは「メッセージパッシング」についてのお話。
今までは「make-*」系の手続きは、外部から与えられたデータを、consを使って型タグをつけて「データオブジェクト」として保持していた。
今度は、与えられたデータを「手続きオブジェクト」として返し、それに対する操作をその「手続きオブジェクトの中に定義」して管理する方法を紹介する。
まずはコードを紹介。
(define (square x) (* x x)) (define (make-from-real-imag x y) ;xとyを扱う方法を「手続きオブジェクト」として実装する。 (define (dispatch op) (cond ((eq? op 'real-part) x) ((eq? op 'imag-part) y) ((eq? op 'magnitude) (sqrt (+ (square x) (square y)))) ((eq? op 'angle) (atan y x)) (else (error "Unknow op -- MAKE-FROM-REAL-IMAG" op)))) ;外部からxとyを与えられて生成されたdispatch手続きを返却する。 ;Lisp/schemeはガーベッジコレクションを標準装備していることになっているため、 ;外部から渡されたxとyへの参照を、dispatchが保持した形で返却されるため、 ;xとyは返却されたdispatchがどこからも参照されなくなるまで保持される。 dispatch)
コードを見ると分かると思うが、使い方はこんな感じになる。
gosh> (define complex1 (make-from-real-imag 2 5))
complex1
gosh> complex1
#
gosh> (complex1 'real-part)
2
gosh> (complex1 'imag-part)
5
gosh> (complex1 'magnitude)
5.385164807134504
gosh> (complex1 'angle)
1.1902899496825317
gosh> (define complex2 (make-from-real-imag 3 4))
complex2
gosh> (complex2 'real-part)
3
gosh> (complex2 'imag-part)
4
gosh> (complex2 'magnitude)
5.0
gosh> (complex2 'angle)
0.9272952180016122
gosh>
生成したデータそのものが手続きであるため、引数に「どのデータを取得したい」という情報を与えてやると、該当するロジックが実行され、お目当てのデータが取得できる感じ。
これを「メッセージパッシング」というらしいよ。