CPS / Continuations StackOverflowError для (tail-) рекурсивных функций - PullRequest
4 голосов
/ 11 мая 2010

есть ли способ использовать хвостовую рекурсивную функцию внутри CPS, не генерирующую StackOverflow?

import scala.util.continuations._
object CPSStackOverflow {
  def main(args: Array[String]) = {
    reset {
      def recurse(i: Int): Unit @suspendable = {
        println(i)
        shift { k: (Unit => Unit) =>
          k( () ) // just continue
        }
        recurse(i + 1)
      }
      recurse(1)
    }
  }
}

приводит к следующей ошибке StackOverflowError:

1298
1299
1300
Exception in thread "main" java.lang.StackOverflowError
    at java.nio.CharBuffer.wrap(CharBuffer.java:350)
    at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:246)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
    at java.io.PrintStream.write(PrintStream.java:476)
    at java.io.PrintStream.print(PrintStream.java:619)
    at java.io.PrintStream.println(PrintStream.java:773)
    at scala.Console$.println(Console.scala:198)
    at scala.Predef$.println(Predef.scala:182)
    at test.CPSStackOverflow$$anonfun$main$1.recurse$1(CPSStackOverflow.scala:9)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$2.apply(CPSStackOverflow.scala:13)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$2.apply(CPSStackOverflow.scala:10)
    at scala.util.continuations.ControlContext$$anonfun$flatMap$2$$anonfun$apply$2.apply(ControlContext.scala:71)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:11)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:10)
    at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
    at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
    at scala.util.continuations.ControlContext$$anonfun$flatMap$2.apply(ControlContext.scala:68)
    at scala.util.continuations.ControlContext$$anonfun$flatMap$2.apply(ControlContext.scala:67)
    at scala.util.continuations.ControlContext$$anonfun$flatMap$2$$anonfun$apply$2.apply(ControlContext.scala:73)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:11)
    at test.CPSStackOverflow$$anonfun$main$1$$anonfun$recurse$1$1.apply(CPSStackOverflow.scala:10)
    at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
    at scala.util.continuations.package$$anonfun$shiftR$1.apply(package.scala:58)
etc...

Есть ли способ обойти эту ошибку? батуте? разматывание стека с помощью исключения? Спасибо!

Ответы [ 2 ]

1 голос
/ 31 января 2011

Вы вызываете другую функцию внутри продолжения. Scala не поддерживает хвостовую рекурсию кросс-метода, потому что JVM не поддерживает.

1 голос
/ 12 мая 2010

Вы можете запустить Java с -Xss2M, однако эта ошибка может возникнуть только через тысячу итераций позже. Пока ваш метод не является хвостовым рекурсивным, вы не сможете обойти эту проблему.

...