2010-05-11 4 views
4

Y a-t-il un moyen d'avoir une fonction récursive dans CPS sans lancer StackOverflow?CPS/Continuations StackOverflowError sur les fonctions récursives (arrière)

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) 
    } 
    } 
} 

résultats en StackOverflowError suivants:

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... 

Toute façon de contourner cette erreur? trampoline? stack-unwinding en lançant des exceptions? Merci!

+0

Au moins la boucle while, bien que réécrite par le plugin CPS-compilateur, fonctionne sans tuer la pile ... – hotzen

Répondre

1

Vous appelez une autre fonction dans la suite. Scala ne prend pas en charge la récursion de queue inter-méthodes, car la JVM ne le fait pas.

+1

placez une annotation '@ tailrec' sur' recurse' et le compilateur vous dira quand il pourra ' t remplir votre demande de récurrence de la queue. –

1

Vous pouvez exécuter Java avec -Xss2M, mais cette erreur peut se produire seulement un millier d'itérations plus tard. Tant que votre méthode n'est pas récursive, vous ne pourrez pas contourner ce problème.

Questions connexes