由于缺少括号,F#尾部调用被打破

时间:2015-03-07 20:04:59

标签: f# tail-recursion tail-call-optimization tail-call

在使用F#团队blog article测试F#尾调用时,我发现几乎相同的代码具有相同的结果,但是不同的 IL虽然代码中只有括号不同。

下一代码由编译器优化,我在IL的末尾看到br.s IL_0000,没有调用sumSoFar

let rec loopAndSum aList sumSoFar = 
    match aList with
    | [] -> sumSoFar
    | x :: xs -> 
        loopAndSum xs (sumSoFar + x)

loopAndSum [ 1..5 ] 0 
|> printfn "sum: %i"

但是这个部分没有被编译器优化,并且它在IL的末尾附近有call bla_bla.loopAndSum

let rec loopAndSum aList sumSoFar = 
    match aList with
    | [] -> sumSoFar
    | x :: xs -> 
        loopAndSum xs sumSoFar + x

loopAndSum [ 1..5 ] 0 
|> printfn "sum: %i"

这些示例仅与sumSoFar + x周围的括号不同。 您可以使用它并在.NET Fiddle处查看IL。

有人知道为什么括号很重要吗?

1 个答案:

答案 0 :(得分:4)

函数应用程序的优先级高于任何运算符。所以没有括号,它等同于:

(loopAndSum xs sumSoFar) + x

因此它不是尾调用:在递归调用之后执行添加。只是偶然的结果值是正确的。