0

我正在从这里阅读 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

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

4

1 回答 1

1

您已经发现需要更改cps.cpsParam

如果您在 REPL 之外的内部编译该行object,它实际上可以正常工作。您所看到的是 REPL 在幕后所做的工作以打印出对其读取内容的评估。在 REPL 中,当您键入并看到类似以下内容时:

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

由于某种我无法解释的原因,生成f: ()Int字符串的代码将结果分配f给一个虚拟变量,如下所示lazy val $result = f:如果您使用该-Xprint:parser选项启动 REPL,您可以看到它的实际效果。它将揭露很多幕后发生的事情。

不幸的是,创建虚拟赋值的代码不理解延续插件,合成代码无效。

要解决此问题,您可以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 不会尝试将结果分配给 a val,这就是您的第二个示例有效的原因。

于 2013-07-04T02:49:31.287 回答