简体   繁体   中英

F# tail call broken by lack of parentheses

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM