2014-02-25 4 views
3

forever` Functional Programming in Scala에서 forever 콤비를 보면`에 : 나는에 StackOverflow에 달렸다StackOverflow의 연결자

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

,이 책은 설명한다. 위의 테스트 3 회를 실행 한 후

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

: 나는 ScalaTest 테스트를 생성, 그리고

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

을 :

그런 다음, 나는 그것이마다 t 액세스됩니다 증가하는 count 변수를 추가 매번 ~ 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을 얻으면 코드가 아닌 설정에서 문제를 해결해야합니다. 이 경우 스택이 넘치지 않도록 trampolining을 사용합니다. 아주 좋은 설명은 여기에서 찾을 수 있습니다 : http://blog.higher-order.com/assets/trampolines.pdf