我正在阅读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
你能解释一下为什么会这样吗?
答案 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
,这就是您的第二个示例有效的原因。