Scala 延续和理解——什么';什么是不相容性?
我对Scala还不熟悉,我正试图用头脑去思考续集 我试图重现Scala 延续和理解——什么';什么是不相容性?,scala,generator,yield,continuations,continuation-passing,Scala,Generator,Yield,Continuations,Continuation Passing,我对Scala还不熟悉,我正试图用头脑去思考续集 我试图重现yield-returnC#语句 下面,我编写了以下代码: package com.company.scalatest import scala.util.continuations._; object GenTest { val gen = new Generator[Int] { def produce = { yieldValue(1) yieldValue(2) yieldV
yield-return
C#语句
下面,我编写了以下代码:
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(())
()
}
}
为什么我会出现这个错误,有没有比while循环更干净的方法来解决这个问题?
谢谢首先让我们看看编译
gen2
需要什么
object CpsConversions {
import scala.collection.IterableLike
import scala.util.continuations._
implicit def cpsIterable[A, Repr](xs: IterableLike[A, Repr]) = new {
def cps = new {
def foreach[B](f: A => Any@cpsParam[Unit, Unit]): Unit@cpsParam[Unit, Unit] = {
val it = xs.iterator
while(it.hasNext) f(it.next)
}
}
}
}
object GenTest {
import CpsConversions.cpsIterable
val gen2 = new Generator[Int] {
def produce = {
var ints = List(1, 2, 3, 42)
ints.cps.foreach((theInt) => yieldValue(theInt))
}
}
现在让我们来看看发生了什么。原始的gen2
无法在以下行编译:
ints.foreach((theInt) => yieldValue(theInt))
由于yieldValue
的类型包括@cpsParam
注释,因此continuations插件将传递给foreach
方法的函数转换为以下类型之一:
Int => Unit @cpsParam[Unit,Unit]
在List[Int]
的层次结构中,您将看到foreach
定义为:
foreach [U] (f: (Int) ⇒ U): Unit
这是一个问题,因为类型不匹配,Scala不知道如何从Int=>U
到Int=>Unit@cpsParam[Unit,Unit]
。为了修复它,我在隐式转换中添加了foreach
的CPS版本,您可以通过在任何IterableLike
上调用CPS
来访问它
如果这种隐式转换不需要显式的cps
调用,那就太好了,但是我还没有找到一种方法让Scala编译器认识到这种隐式转换的适用性,从而将新的foreach
推到您的列表中。这可能与编译器使用continuations插件的顺序有关,但我对这个过程知之甚少,无法确定
因此,这对
foreach
来说都很好。您的问题涉及理解,这将需要定义过滤器
、映射
、或平面映射
(取决于理解过程中的内容)。我已经在我上面的评论中的链接中实现了这些,它扩展了上面的cpscoverations
对象,以便于理解。我不想找到一个答案,告诉我如何使用Scala continuations重现“收益率回报”。我正在寻找示例中的“gen2”不起作用的原因。“收益回报”正是我遇到这个问题的背景。我将主题改为更适合您实际问题的主题。为什么gen2
不起作用的答案主要与continuations编译器插件如何将移位和重置转换为基础ControlContext实例有关。今天晚些时候,我会给出一个正确的答案,但现在我写了一篇关于这个主题的简介:
foreach [U] (f: (Int) ⇒ U): Unit