2014-02-25 29 views
3

望着forever組合子從Functional Programming in Scala的StackOverflow上`forever` Combinator的

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每次執行的堆棧內存佔用了多少?

回答

2

由於堆棧大小,它取得該數字。大小可以設置爲-Xss,默認值因平臺和VM /版本而異。但一般來說,當你得到一個StackOverflowError你應該嘗試解決你的代碼中的問題,而不是你的設置。在這種情況下,我會使用蹦牀來防止堆棧溢出。一個非常好的解釋可以在這裏找到:http://blog.higher-order.com/assets/trampolines.pdf