2012-02-14 25 views
5

Estoy trabajando en el libro Real-World Functional Programming, e intenté encontrar mi propio ejemplo de recursividad final antes de leer el ejemplo del libro (listado 10.2, p.285). El ejemplo del libro funciona; el mío causa un desbordamiento de la pila.¿Por qué no es esta cola recursiva?

He encontrado que si uso un argumento de tupla o precalculo a + accum entonces el mío funcionará. Quiero entender por qué.

let rnd = new System.Random() 
let test2 = List.init 1000000 (fun _ -> rnd.Next(-50, 51)) 

let rec sum2 list accum = 
    match list with 
    | [] -> accum 
    | a::b -> sum2 b a + accum 

let result = sum2 test2 0 

printfn "%d" result 

Respuesta

10
sum2 b a + accum 

Tenga en cuenta que esto se analiza como (sum2 b a) + accum, no sum2 b (a + accum).

Así que esto llama sum2 b a. Luego toma el resultado de esa llamada y le agrega accum. Entonces la última expresión evaluada es la adición, no la llamada al sum2. Por lo tanto, la llamada a sum2 no es una llamada de cola.

5

Tal vez el compilador es la lectura

a::b -> (sum2 b a) + accum 

en lugar de

a::b -> sum2 b (a + accum) 
+0

Aaargh! Tú y @sepp2k están en el blanco. Es orden de evaluación. Los paréntesis lo arreglan. – TrueWill

+3

Generalmente sobre-paréntesis todo, ya que he encontrado que es el mal menor. Yay ceceo en común! – gpeche