Question

I am reading the scala continuation blog post from here. Unfortunately this does not work on scala 2.10.0:

def f():Int @cps[Int,Int] = {shift { (k:Int=>Int) => k(6) } - 1} 
<console>:10: error: wrong number of type arguments for util.continuations.cps, should be 1
       def f():Int @cps[Int,Int] = {shift { (k:Int=>Int) => k(6) } - 1} 
                ^
<console>:10: error: type mismatch;
 found   : Int @scala.util.continuations.cpsSynth 

@scala.util.continuations.cpsParam[Int,Int]
 required: Int
       def f():Int @cps[Int,Int] = {shift { (k:Int=>Int) => k(6) } - 1} 

Same deal if I tried the suggested type:

def f():Int @cpsParam[Int,Int] = {shift { (k:Int=>Int) => k(6) } - 1} 
<console>:4: error: type mismatch;
 found   : Int @scala.util.continuations.cpsSynth
@scala.util.continuations.cpsParam[Int,Int]
 required: Int
object $eval {

If I add an unused input parameter, it does not complain:

def f2(x:Int):Int @cpsParam[Int, Int=>Int] = shift { (k:Int=>Int) => k } -1
f2: (x: Int)Int @scala.util.continuations.cpsParam[Int,Int => Int]

reset(f2(1))(0)
res12: Int = -1

Can you explain why this is happening?

Was it helpful?

Solution

You already figured out you need to change cps with cpsParam.

If you compile the line outside of the REPL inside an object, it will actually work fine. What you see is an artifact of what the REPL does behind the scene to print out the evaluation of what it reads. In the REPL when you type and see something like:

scala> def f() = 1
f: ()Int

For some reason that I cannot explain, the code that generates the f: ()Int string assigns the result of f to a dummy variable like this: lazy val $result = f. You can see it in action if you start the REPL with the -Xprint:parser option. It will expose a lot of what happens behind the scene.

Unfortunately that code that creates the dummy assignment does not understand the continuation plug-in and the synthetized code is not valid.

To work around this you can define f inside an object in a single statement which will circumvent the lazy val statement:

$ scala -P:continuations:enable               
Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_09).
Type in expressions to have them evaluated.
Type :help for more information.

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

scala> object F { def f():Int @cpsParam[Int,Int] = {shift { (k:Int=>Int) => k(6) } - 1} }
defined module F

scala> reset{ F.f() }
res0: Int = 5

When you add a dummy parameter to f, the REPL does not try to assign the result to a val, so that's why your second example works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top