Scalaの限定継続のshiftだけを含む関数オブジェクトを作れるかを実験

関数オブジェクトの定義の中にshiftを入れて、関数オブジェクトを別のメソッドに渡す、そのメソッドではresetの中でその関数オブジェクトを呼び出す、ってのができるかを実験した。

import scala.util.continuations.cpsParam;
import scala.util.continuations.reset;
import scala.util.continuations.shift;

object test {

  def main(args: Array[String]){

    val f: Int => Long @cpsParam[String, (String, String)] = {
      a: Int =>
      shift { ctx: (Long => String) =>
        val s = ctx(a * 10000L);
        (s, "test:f");
      }
    }

    val g: Int => Long @cpsParam[String, (String, String)] = {
      a: Int =>
      shift { ctx: (Long => String) =>
        val s = ctx(a * 20000L);
        (s, "test:g");
      }
    }

    sub(f);
    sub(g);

  }

  private def sub(f: Int => Long @cpsParam[String, (String, String)]){

    val result: (String, String) = reset {
      val a: Int = 123;
      val b: Long = f(a);
      (a + b).toString;
    }

    println(result);

  }

}
$ scalac -P:continuations:enable test.scala && scala test
(1230123,test:f)
(2460123,test:g)

作れるみたい。

REPLで限定継続を試すには、コンパイラのオプションと同様に

$ scala -P:continuations:enable

とする必要がある模様。

$ scala
Welcome to Scala version 2.9.0.1 (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.util.continuations._;
import scala.util.continuations._

scala> val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
<console>:10: error: this code must be compiled with the Scala continuations plugin enabled
       val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
                                 ^

scala> :quit
$ scala -P:continuations:enable
Welcome to Scala version 2.9.0.1 (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.util.continuations._;
import scala.util.continuations._

scala> val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
f: (Int) => Long @scala.util.continuations.cpsParam[String,(String, java.lang.String)] = <function1>

scala> f(3)
None/None/Some((String,(String, java.lang.String)))
<console>:12: error: found cps expression in non-cps position
       f(3)
        ^

scala> reset { f(3).toString; }
res1: (String, java.lang.String) = (30000,test:f)