在使用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。
有人知道为什么括号很重要吗?
答案 0 :(得分:4)
函数应用程序的优先级高于任何运算符。所以没有括号,它等同于:
(loopAndSum xs sumSoFar) + x
因此它不是尾调用:在递归调用之后执行添加。只是偶然的结果值是正确的。