Вызов хвоста F# сломан из-за отсутствия скобок

При тестировании вызовов F# tail в статье блога команды F# я обнаружил, что почти один и тот же код имеет одинаковый результат, но разные IL, хотя в коде отличаются только круглые скобки.

Следующий код оптимизирован компилятором, и я вижу br.s IL_0000 в конце IL и нет звонков sumSoFar

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

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

Но этот кусок не оптимизирован компилятором и имеет call bla_bla.loopAndSum близко к концу IL.

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

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

Эти примеры отличаются только круглыми скобками sumSoFar + x, Вы можете поиграть с ним и посмотреть на IL на .NET Fiddle.

Кто-нибудь знает, почему круглые скобки имеют значение?

1 ответ

Решение

Функция приложения имеет более высокий приоритет, чем любой оператор. Таким образом, без скобок, это эквивалентно:

(loopAndSum xs sumSoFar) + x

Поэтому это не конечный вызов: сложение выполняется после рекурсивного вызова. Это просто случайно, что значение результата является правильным.

Другие вопросы по тегам