StackOverflow在`forever` Combinator上

时间:2014-02-25 03:29:10

标签: scala stack-overflow combinators

查看来自Functional Programming in Scalaforever组合器:

trait AddlCombinators[F[_]] extends Monad[F] with Functor[F] {
      def forever[A, B](a: F[A]): F[B] = {
        lazy val t: F[B] = forever(a)
        flatMap(a)(_ => t)
      }
}

本书解释说,我遇到了StackOverflow。

然后,我添加了一个count变量,每次t访问时都会递增它:

var count = 0
def forever[A, B](a: F[A]): F[B] = {
  lazy val t = { println(count); count = count + 1; forever(a) }
}

然后,我创建了一个ScalaTest测试:

 "running forever" should "throw a StackOverflow exception" in {
        val listCombinator = new AddlCombinators[List] {

        // omitted implementation of `Monad[List]` and `Functor[List]`
        }    
        listCombinator.forever(List(1))
      }
}

运行上述测试3次后,每次都会失败~1129 / 1130.

1129
[info] TestCombinators:
[info] running forever
[trace] Stack trace suppressed: run last test:testOnly for the full output.
[error] Could not run test test.TestCombinators: java.lang.StackOverflowError

为什么在崩溃之前达到那个数字?另外,如何判断forever每次执行的堆栈内存占多少?

1 个答案:

答案 0 :(得分:2)

由于堆栈大小,它达到了这个数字。可以使用-Xss设置大小,默认值因平台和VM /版本而异。但是一般来说,当你得到一个StackOverflowError时,你应该尝试解决代码中的问题,而不是你的设置。在这种情况下,我会使用trampolining来防止堆栈溢出。可在此处找到一个非常好的解释:http://blog.higher-order.com/assets/trampolines.pdf