我意识到这与 SO 问题的通常意义背道而驰,但是即使我认为它不应该工作,以下代码仍然有效。下面是一个小的 Scala 程序,它使用带有 while 循环的延续。根据我对延续传递风格的理解,这段代码应该会通过为 while 循环的每次迭代向堆栈添加一个帧来产生堆栈溢出错误。但是,它工作得很好。
import util.continuations.{shift, reset}
class InfiniteCounter extends Iterator[Int] {
var count = 0
var callback: Unit=>Unit = null
reset {
while (true) {
shift {f: (Unit=>Unit) =>
callback = f
}
count += 1
}
}
def hasNext: Boolean = true
def next(): Int = {
callback()
count
}
}
object Experiment3 {
def main(args: Array[String]) {
val counter = new InfiniteCounter()
println(counter.next())
println("Hello")
println(counter.next())
for (i <- 0 until 100000000) {
counter.next()
}
println(counter.next())
}
}
输出是:
1
Hello
2
100000003
我的问题是:为什么没有堆栈溢出?Scala 编译器是在做尾调用优化(我认为它不能用延续做)还是有其他事情发生?
(此实验与运行它所需的 sbt 配置一起在 github 上:https ://github.com/jcrudy/scala-continuation-experiments 。请参阅提交 7cec9befcf58820b925bb222bc25f2a48cbec4a6)