为什么这不是尾递归?

时间:2012-02-14 14:01:25

标签: recursion f# tail-recursion

我正在阅读这本书Real-World Functional Programming,我试着在阅读本书的例子之前提出我自己的尾递归示例(见10.2,第265页)。这本书的例子有效;我的堆栈溢出。

我发现如果我使用元组参数或预先计算a + accum,那么我的工作就可以了。我想了解原因。

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

2 个答案:

答案 0 :(得分:10)

sum2 b a + accum

请注意,这被解析为(sum2 b a) + accum,而不是sum2 b (a + accum)

所以这会调用sum2 b a。然后它接受该调用的结果并向其添加accum。所以评估的最后一个表达式是加法,而不是对sum2的调用。因此,对sum2的调用不是尾调用。

答案 1 :(得分:5)

也许编译器在阅读

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

而不是

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