これは SO の質問の通常の意味に反していることは認識していますが、次のコードは機能しないはずですが、機能します。以下は、while ループで継続を使用する小さな Scala プログラムです。継続渡しスタイルに関する私の理解によれば、このコードは、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 を参照)