言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

継続渡し形式(CPS)変換とは何か?

継続とは何かが分かったので、継続渡し形式とは何かについて調べてみた。

http://karetta.jp/book-node/kahua-seminar2/000511 を読むと、CPS に call/cc は必要無い事が分かった。がっくり。と言う事で、このページの例を HaskellSqueak に写経しながら勉強。

-- 階乗の Haskell 再帰版
fact 0 = 1
fact n = n * fact (n - 1)

-- CPS 版で書くとこうなる。(fact_cps 10 id => 3628800)
fact_cps 0 cont = cont 1
fact_cps n cont = fact_cps (n - 1) (\a -> cont (n * a))

Scheme より滅茶苦茶分かりやすいのはパターンマッチの威力か。ちなみに Squeak Smalltalk では。

!Number methodsFor: 'factorial' stamp: 'tak 8/30/2007 00:50'!
fact
	"10 fact"
	self = 0 ifTrue: [^ 1].
	^ self * (self - 1) fact! !

!Number methodsFor: 'factorial' stamp: 'tak 8/30/2007 00:54'!
factCPS: aBlock
	"10 factCPS: [:a | a]"
	self = 0 ifTrue: [^ aBlock value: 1].
	^ self - 1 factCPS: [:a | aBlock value: self * a].! !

Smalltalk はデバッガが使いやすいので、こういうややこしい関数の動作を調べるには最適だ(テキストで読むソースが醜いのは愛嬌という事にして)。とにかく、パズルとしては面白いような気もするけど、まだ利点がわからん。。。勉強を続けます。