Scala の継続を試してみる
前回の Scala 勉強会 in 渋谷 で [twitter:@cooldaemon] さんが発表していた Scala の継続の話を聞いて、とても気になったので Scala の継続を見てみる。
継続についてのお話にインスパイアされて Scala の継続を見てみる。
Scala の継続は限定継続と言うらしい。
細かいことは こちら 参照。
おおざっぱに言うと、継続する範囲を限定して継続が使えると言うことらしい。
参考 Scala の限定継続(Delimited Continuations) - なんとなくな Developer のメモ
試したソース
import scala.util.continuations.{reset, shift} import scala.actors.Actor.{self, actor} def main() { println("start %s".format(self)) // (1) val result = reset { val x = shift {ctx : (Int => Int) => { Thread.sleep(10) println("call/cc") // (2) val c = ctx(ctx(10)) // この呼び出して shift の次の処理 (nextShift) へ println("c %s".format(c)) println("cont") // (3) c + 1 // この式の値が reset の結果となる }} // nextShift println("x %s".format(x)) println("shiftted %s".format(self)) // (4) x*2 // このブロックを抜けると ctx の呼び出し元に戻る } println("result %s".format(result)) // (5) println("finish %s".format(self)) } main()
実行結果
実行する際は -P:continuations:enable として継続プラグインを有効にしてやる必要がある。
$ scala -P:continuations:enable cont.scala start scala.actors.ActorProxy@194d372 call/cc x 10 shiftted scala.actors.ActorProxy@194d372 x 20 shiftted scala.actors.ActorProxy@194d372 c 40 cont result 41 finish scala.actors.ActorProxy@194d372
処理の流れとしては
1 -> 2 -> 4 -> 4 -> 3 -> 5
となっている。
reset で継続範囲を指定し、 shift で継続を生成する。
shift は Scheme で言うところの call-with-current-continuation(call/cc) にあたる。
大体の流れはコメントに書いたので省略。
これを使うと actor を使わなくても この ネタをより自然に書けそうなので書いてみようと思う。