Groovyの再帰処理(trampoline)についてひとつ分かったこと
はじめに
Groovyのクロージャ(Closure)には.trampolineってメソッドがあって、これをうまい感じに使うと末尾再帰を最適化してくれる。
よしやってみよう
では、簡単な合計値を求めるサンプルを再帰処理で。
java.lang.StackOverflowError
お約束。
よし、今こそトランポリンだ!
groovy.lang.MissingMethodException: No signature of method: java.lang.Integer.plus() is applicable for argument types: (groovy.lang.TrampolineClosure) values: [groovy.lang.TrampolineClosure@509c6c30]
あれ?Integer.plus()?あ…もしかして…。
これが最後の恋であるように*1
ふぅ、やっと動いた。trampolineで遊ぶときは、ほんとに最後の最後はtrampolineしか呼んじゃダメってことなんですね…。trampolineを呼ぶときは最後の恋と覚えましょう(謎)
考察
リストが来たらカーしたものとクダーを再帰に渡して返って来た結果をプラスして返すっていう常套手段がこれでは使えない。最後の例では仕方なくsumという変数を引き渡すようにして対応した。うーん、なんとかならんもんだろうか。
まぁ、それはそれとして最後にまとめておくか。
trampolineする際の大人のマナー
- クロージャ内の最後の部分で引数ありtrampolineのみを呼び出す
- 内部でtrampolineしているクロージャを使う場合は、引数なしtrampolineメソッドを呼び出して、trampolineできるようにしてから使う