I realize this is counter to the usual sense of SO questions, but the following code works even though I think it should not work. Below is a small Scala program that uses continuations with a while loop. According to my understanding of continuation passing style, this code should produce a stack overflow error by adding a frame to the stack for each iteration of the while loop. However, it works just fine.
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())
}
}
The output is:
1
Hello
2
100000003
My question is: why is there no stack overflow? Is the Scala compiler doing tail call optimization (which I thought it couldn't do with continuations) or is there some other thing going on?
(This experiment is on github along with the sbt configuration needed to run it: https://github.com/jcrudy/scala-continuation-experiments. See commit 7cec9befcf58820b925bb222bc25f2a48cbec4a6)