Вызов хвоста 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
Поэтому это не конечный вызов: сложение выполняется после рекурсивного вызова. Это просто случайно, что значение результата является правильным.