Scala Advent Calendar jp 2010 の 12/18 - Loan pattern in CPS を読んだ感想
Loan pattern in cps - hano - GitHub
Perl の Coro に慣れていると、Scala の限定継続は使い難いなーと思っていたら、認識を覆されたのでメモ。私の理解不足でしたと。
以下に簡単なサンプルを用意しました。
object Sample { import scala.util.continuations.{reset, shift} def main (args:Array[String]) { val alphabets = "abc" val numbers = "123" reset { val alpabet = shift { (k: Char => Unit) => alphabets.foreach(k) } // (1) val number = shift { (k: Char => Unit) => numbers.foreach(k) } // (2) println(alpabet.toString + '-' + number.toString) // (3) } } }
reset や shift を使用する場合、コンパイルオプションとして "-P:continuations:enable" を追加する必要があります。
私は、MacPorts から Scala をインストールしているので下記でコンパイルしています。
% fsc-2.8 -P:continuations:enable Sample.scala
これを実行すると下記が出力されます。
% scala-2.8 Sample a-1 a-2 a-3 b-1 b-2 b-3 c-1 c-2 c-3
上記の例だと、(1)-(3) が alpabet = shift {...} の継続の範囲で、(2)-(3) が number = shift {...} の継続の範囲となります。
誤解を招く表現なので訂正。上記の例だと、(1)-(3) が alpabet = shift {...} 内の k() の範囲で、(2)-(3) が number = shift {...} 内の k() の範囲となります。
ここまで理解していれば、上記の Loan pattern in cps は読み下せるかなーと思いますが如何でしょうか。
もともと私が想定していた、Perl の AnyEvent + Coro のような使い方も追記しておきます
object TimerSample { import scala.util.continuations.{reset, shift} import java.util.{Timer, TimerTask} def main (args:Array[String]) { val timer = new Timer() def sleep(delay: Int) = shift { k: (Unit => Unit) => timer.schedule(new TimerTask { def run = k() }, delay) } reset { println("start:" + Thread.currentThread) sleep(10000) timer.cancel println("end:" + Thread.currentThread) } } }
イベントドリブンと継続は相性が良いです。