Ошибка типа продолжения Scala

Я читаю сообщение в блоге о продолжении 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

Можете ли вы объяснить, почему это происходит?


person Zhi Han    schedule 03.07.2013    source источник


Ответы (1)


Вы уже поняли, что вам нужно заменить cps на cpsParam.

Если вы скомпилируете строку вне REPL внутри object, она будет работать нормально. То, что вы видите, является артефактом того, что REPL делает за кулисами, чтобы распечатать оценку того, что он читает. В REPL, когда вы печатаете и видите что-то вроде:

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

По какой-то причине, которую я не могу объяснить, код, генерирующий строку f: ()Int, присваивает результат f фиктивной переменной вроде этой: lazy val $result = f. Вы можете увидеть это в действии, если запустите REPL с опцией -Xprint:parser. Это раскроет многое из того, что происходит за кулисами.

К сожалению, тот код, который создает фиктивное назначение, не понимает подключаемый модуль продолжения, и синтезированный код недействителен.

Чтобы обойти это, вы можете определить 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, поэтому ваш второй пример работает.

person huynhjl    schedule 04.07.2013
comment
Это интересно. Спасибо за ваш ответ. - person Zhi Han; 05.07.2013