2007/06/23

Schemeの多値の正体は継続

SICPでは「多値」を表立って使うことはない。ただ、5.2.2で2種類のリストをやりとりするときに2変数のプロシージャを使った一見するとトリッキーな処理が登場して、これが実は多値なんだよという種明かしを脚注4でやっている。さらに、そのトリッキーな2変数プロシージャのことを継続(continuation)と呼ぶと説明している。

多値も継続だったのか。

噛みしめるために小さな例を考えてみた。つぎのプロシージャ one は、プロシージャ sincos が返す 2 値を受け取り、その 2 乗和を返す。sincos は引数の角度に対する sin の値と cos の値を返すので、プロシージャ one は引数にどんな数値を指定しても実数の 1 を返す。
(define (one rad)
(receive (sin cos)
(sincos rad)
(+ (* sin sin) (* cos cos))))

(define (sincos rad)
(values
(sin rad) (cos rad)))
このプロシージャ one は、values や receive という組み込みの多値のしくみを使わなくても、つぎのように継続を表すプロシージャ cont を使って多値を模倣できる。
(define (one rad)
(sincos
rad
(lambda (sine cosine)
(+ (* sine sine) (* cosine cosine)))))

(define (sincos rad cont)
(cont (sin rad) (cos rad)))
いちおう実行結果。
gosh>(one 123456)
1.0
gosh>(one -9876)
1.0


まとめ

計算の一部または全部をどうにかしたい場合があって(よその関数に渡したいとか、ちょっと保留しておきたいとか)、そのときの定石は「プロシージャでくるんでしまえ」。で、そういうプロシージャのことを「継続」(continuation)と呼ぶ。

No comments :