(尾)递归函数上的 CPS/Continuations StackOverflowError

发布于 2024-09-01 11:17:05 字数 2573 浏览 7 评论 0原文

有没有办法让 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...

有办法避免此错误吗?蹦床?通过抛出异常来展开堆栈? 谢谢!

is there any way to have a tail-recursive function inside CPS not throwing a 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)
    }
  }
}

results in following 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...

Any way to circumvent this error? trampolining? stack-unwinding by throwing exceptions?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无人接听 2024-09-08 11:17:05

您正在继续中调用另一个函数。 Scala 不支持跨方法尾递归,因为 JVM 不支持。

You are calling another function inside the continuation. Scala doesn't support cross-method tail recursion, because the JVM doesn't.

千纸鹤带着心事 2024-09-08 11:17:05

您可以使用 -Xss2M 运行 Java,但是该错误可能仅在一千次迭代后发生。只要你的方法不是尾递归,你就无法解决这个问题。

You can run Java with -Xss2M, however that error might occur only a thousand iterations later. As long as your method is not tail recursive you will not be able to get around this problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文