【发布时间】:2012-02-14 14:16:00
【问题描述】:
我是 Scala 的新手,并试图围绕延续
我正在尝试重现 yield return C# 语句。
按照this post,我写了以下代码:
package com.company.scalatest
import scala.util.continuations._;
object GenTest {
val gen = new Generator[Int] {
def produce = {
yieldValue(1)
yieldValue(2)
yieldValue(3)
yieldValue(42)
}
}
// Does not compile :(
// val gen2 = new Generator[Int] {
// def produce = {
// var ints = List(1, 2, 3, 42);
//
// ints.foreach((theInt) => yieldValue(theInt));
// }
// }
// But this works?
val gen3 = new Generator[Int] {
def produce = {
var ints = List(1, 2, 3, 42);
var i = 0;
while (i < ints.length) {
yieldValue(ints(i));
i = i + 1;
}
}
}
def main(args: Array[String]): Unit = {
gen.foreach(println);
// gen2.foreach(println);
gen3.foreach(println);
}
}
abstract class Generator[E] {
var loopFn: (E => Unit) = null
def produce(): Unit @cps[Unit]
def foreach(f: => (E => Unit)): Unit = {
loopFn = f
reset[Unit, Unit](produce)
}
def yieldValue(value: E) =
shift { genK: (Unit => Unit) =>
loopFn(value)
genK(())
()
}
}
如您所见,gen2 被注释掉,因为它无法编译。由于我可以使用 while 循环轻松迭代列表的内容(请参阅 gen3),因此我希望 foreach 循环也能正常工作。
编译错误如下:
no type parameters for method foreach: (f: Int => B)Unit exist so that
it can be applied to arguments (Int => Unit @scala.util.continuations.cpsParam[Unit,Unit])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Int => Unit @scala.util.continuations.cpsParam[Unit,Unit]
required: Int => ?B
为什么我会收到此错误,有没有办法使用比 while 循环更简洁的方法来解决此问题?
谢谢
【问题讨论】:
-
我不是在寻找一个答案,告诉我如何使用 Scala 延续来重现“收益回报”。我正在寻找示例中的“gen2”不起作用的原因。 “收益回报”只是我遇到此问题的上下文。
-
我将主题更改为更适合您实际问题的内容。
-
gen2不起作用的答案主要与延续编译器插件如何将移位和重置转换为底层 ControlContext 实例有关。我将在今天晚些时候整理出一个正确的答案,但现在我就这个主题写了一个简介:earldouglas.com/monadic-continuations-in-scala
标签: scala generator yield continuations continuation-passing