我正在阅读这本书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
答案 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)