関数型プログラミングの 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
か?