2010-05-11 28 views
7

Tôi đang học F # và tôi không hiểu tại sao sự cố này lại bị treo. Đó là một nỗ lực để giải quyết Project Euler problem 2.F # Seq.initInfinite giving 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 

Phiên bản cuối cùng sẽ gọi hàm tổng (và có giới hạn cao hơn 55), nhưng đây là mã học.

Như vậy, điều này cho phép StackOverflowException. Tuy nhiên, nếu tôi nhận xét trong [1..30] và xóa bỏ Seq.initInfinite, tôi nhận được:

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

Nó dường như được tạo ra mặt hàng theo yêu cầu, như tôi đã mong chờ trong LINQ. Vậy tại sao nó lại nổ tung khi được sử dụng với initInfinite?

+2

+1 để tạo StackOverflowException –

Trả lời

14

Seq.initInfinite trả về một chuỗi bắt đầu tại 0.

Kết quả chức năng fibonacci của bạn trong tình trạng tràn ngăn xếp khi được gọi bằng không, vì nó không bao giờ chạm vào các trường hợp chấm dứt.

Bạn có thể giải quyết việc này bằng cách bắt đầu từ Seq.initInfinite (fun n -> n + 1)

+0

Aargh! Cảm ơn bạn!! Tôi cũng thấy rằng việc đặt takeWhile trước khi bộ lọc sẽ cắt giảm số lần lặp lại. – TrueWill

6

Bạn đang bắt đầu với 0 với initInfinite, sau đó recurses -1, -2, ...

(Bằng cách này, nếu bạn bằng cách sử dụng trình gỡ lỗi Visual Studio, điều này rất dễ chẩn đoán, bằng cách kiểm tra ngăn xếp cuộc gọi và cửa sổ cục bộ.)

+0

+1 để có đề xuất chung tốt. –

Các vấn đề liên quan