Scala延续类型错误

时间:2013-07-03 14:15:26

标签: scala continuations

我正在阅读here的scala延续博文。不幸的是,这不适用于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} 

如果我尝试了建议的类型,那就相同了:

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 {

如果我添加一个未使用的输入参数,它不会抱怨:

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

你能解释一下为什么会这样吗?

1 个答案:

答案 0 :(得分:1)

您已经发现需要使用cps更改cpsParam

如果在object内编译REPL之外的行,它实际上可以正常工作。你看到的是REPL在场景背后所做的工件,用于打印出它所读取内容的评估。在键入时,在REPL中看到类似的内容:

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

由于某些我无法解释的原因,生成f: ()Int字符串的代码会将f的结果分配给虚拟变量,如下所示:lazy val $result = f。如果使用-Xprint:parser选项启动REPL,则可以看到它的运行情况。它将揭示场景背后发生的很多事情。

不幸的是,创建虚拟赋值的代码无法理解continuation插件,并且合成代码无效。

要解决此问题,您可以在单个语句中的对象内定义f,这将绕过惰性val语句:

$ 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

当您向f添加虚拟参数时,REPL不会尝试将结果分配给val,这就是您的第二个示例有效的原因。