Reputation: 856
While testing F# tail calls with F# team blog article I found that almost the same code has the same result but different IL although only parentheses in the code differ.
Next code is optimized by compiler and I see br.s IL_0000
in the end of IL and no calls to sumSoFar
let rec loopAndSum aList sumSoFar =
match aList with
| [] -> sumSoFar
| x :: xs ->
loopAndSum xs (sumSoFar + x)
loopAndSum [ 1..5 ] 0
|> printfn "sum: %i"
But that piece is not optimized by compiler and it has call bla_bla.loopAndSum
near to the end of IL.
let rec loopAndSum aList sumSoFar =
match aList with
| [] -> sumSoFar
| x :: xs ->
loopAndSum xs sumSoFar + x
loopAndSum [ 1..5 ] 0
|> printfn "sum: %i"
These examples differ only with parentheses around sumSoFar + x
.
You can play with it and look at IL at .NET Fiddle.
Does anybody know why parentheses matter?
Upvotes: 0
Views: 98
Reputation: 11372
Function application has higher precedence than any operator. So without the parentheses, it is equivalent to:
(loopAndSum xs sumSoFar) + x
Therefore it is not a tail call: the addition is performed after the recursive call. It is just by chance that the result value is correct.
Upvotes: 4