2010-05-11 10 views
7

estoy aprendiendo C#, y estoy teniendo problemas para entender por qué esto se bloquea. Es un intento de resolver Project Euler problem 2.F # Seq.initInfinite dando 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 

La versión final llamaría a una función de suma (y tendría un límite superior a 55), pero esto es código de aprendizaje.

Como es, esto da una StackOverflowException. Sin embargo, si comento en el [1..30] y comentario la Seq.initInfinite, me sale:

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

Parece estar generando elementos de la demanda, lo que cabe esperar en LINQ. Entonces, ¿por qué explota cuando se usa con initInfinite?

+2

1 para generar StackOverflowException –

Respuesta

14

Seq.initInfinite devuelve una secuencia que comienza en 0.

Sus fibonacci función da como resultado un desbordamiento de pila Cuando se llama con cero, porque nunca llega a los casos de terminación.

Puede resolver este partiendo de Seq.initInfinite (fun n -> n + 1)

+0

Aargh! ¡¡Gracias!! También encontré que poner el takeWhile antes del filtro reduciría el número de iteraciones. – TrueWill

6

Estás empezando con 0 con initInfinite, que luego recursivamente -1, -2, ...

(Por cierto, si estás utilizando el depurador de Visual Studio, esto es fácil de diagnosticar, mediante la comprobación de la ventana y la pila de llamadas locales.)

+0

+1 para una buena sugerencia general. –

Cuestiones relacionadas