2010-05-11 3 views
7

저는 F #을 배우고 있는데 왜 충돌이 발생하는지 이해하는 데 어려움을 겪고 있습니다. 그것은 Project Euler problem 2을 풀기위한 시도입니다.F # Seq.initInfinite StackOverflowException을 제공합니다

let rec fibonacci n = 
    if n = 1 then 
     1 
    elif n = 2 then 
     2 
    else 
     fibonacci (n - 1) + fibonacci (n - 2) 

let debugfibonacci n = 
    printfn "CALC: %d" n 
    fibonacci n 

let isEven n = 
    n % 2 = 0 

let isUnderLimit n = 
    n < 55 

let getSequence = 
    //[1..30] 
    Seq.initInfinite (fun n -> n) 
    |> Seq.map debugfibonacci 
    |> Seq.filter isEven 
    |> Seq.takeWhile isUnderLimit 

Seq.iter (fun x -> printfn "%d" x) getSequence 

마지막 버전은 sum 함수를 호출하며 (55보다 큰 제한이 있음) 코드를 학습합니다.

이 경우 StackOverflowException이 발생합니다. 나는 [1..30]에서 언급하고 Seq.initInfinite을 주석 경우, 내가 얻을 :

그것은 내가 LINQ에서 기대하는 것처럼, 필요에 따라 항목을 생성하는 것으로 보인다
CALC: 1 
CALC: 2 
2 
CALC: 3 
CALC: 4 
CALC: 5 
8 
CALC: 6 
CALC: 7 
CALC: 8 
34 
CALC: 9 
CALC: 10 
CALC: 11

. 그렇다면 initInfinite와 함께 사용하면 왜 폭발합니까?

+2

+1 생성에 StackOverflowException이 발생했습니다. –

답변

14

Seq.initInfinite0에서 시작하는 시퀀스를 반환합니다.

fibonacci 함수는 종료 사례에 절대로 도달하지 않으므로 0으로 호출하면 스택 오버플로가 발생합니다.

당신은 ... 당신은 -1, -2 재귀 initInfinite으로 0부터 시작하고 Seq.initInfinite (fun n -> n + 1)

+0

아아! 고맙습니다!! 나는 또한 필터 앞에 takeWhile을 두는 것이 반복 횟수를 줄이는 것을 발견했다. – TrueWill

6

에서 시작하여이 문제를 해결할 수

(그런데, 당신이 있다면 Visual Studio 디버거를 사용하면 호출 스택과 로컬 창을 확인하여 진단하기 쉽습니다.)

+0

+1 좋은 제안입니다. –