Continuation
自分的にはよくまとまった気がするんだけどどうだろう?
- 関数の最後に自分自身を呼び出すのが末尾再帰。
- Schemeでは末尾再帰でスタックを消費しない(言語仕様)。これが末尾再帰の最適化。
- RubyやHaskellでは末尾再帰の最適化をおこなわない。
- C/Javaのfor文は最適化された末尾再帰ということができる。副作用ありだから、強いて言うならこのときの継続はコンテキストそのもの(になるのかな?)。
- 末尾再帰する関数の引数のひとつに「これから行われるであろう計算をパッケージ化したもの」があって末尾再帰する関数がこれを評価する処理をおこなうなら、それは継続(Continuation)であり、継続渡し(Continuation Passing Style)になるわけだ。
Do this by capturing 'everything we want to do next' as a closure that will take 'what we are about to calculate' as a parameter. ie. a continuation. 「CpsInJava」から
- Spring Web Flowはフローに沿ってあらかじめ継続を(場合によっては複数)用意しといて処理の分岐に応じて切替えるんだろう、多分。
- で、Haskellの場合は遅延評価があるから「継続」ってわざわざ口角泡立てることはないんだ。ただ継続渡しが深くなるとドカーンと一発で脱出したくなるときがあるかもしれない。んでcallCCの引数には現在のContinuationがある、と。
個人的にはかなりスッキリ。shiroさんの「なんでも再帰」「なんでも継続」とHaWikiの「CpsInJava」が特にスマッシュヒットだった。「CpsInJava」はJavaな人なら誰でも読めるハズ。先人たちの素晴らしい仕事に感謝、感謝。
ただRubyのcallccはいまいち掴めなかったので、もうちょっと勉強する。
参考リンク
- http://www.shiro.dreamhost.com/scheme/docs/tailcall-j.html
- http://www.haskell.org/hawiki/CpsInJava
- http://i.loveruby.net/ja/rhg/cd/continuation.html
- http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=%B7%D1%C2%B3
- http://blog.livedoor.jp/dankogai/archives/50043931.html
- http://www.shiro.dreamhost.com/scheme/docs/cont-j.html
- http://www.haskell.org/hawiki/ContinuationPassingStyle