継続とは何かが分かったので、継続渡し形式とは何かについて調べてみた。
http://karetta.jp/book-node/kahua-seminar2/000511 を読むと、CPS に call/cc は必要無い事が分かった。がっくり。と言う事で、このページの例を Haskell と Squeak に写経しながら勉強。
-- 階乗の 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 はデバッガが使いやすいので、こういうややこしい関数の動作を調べるには最適だ(テキストで読むソースが醜いのは愛嬌という事にして)。とにかく、パズルとしては面白いような気もするけど、まだ利点がわからん。。。勉強を続けます。