Почему F # не компилирует Currying в отдельные функции?
Итак, я пытаюсь изучить F #, и, изучая новые вещи, мне нравится смотреть на IL, чтобы увидеть, что происходит под обложками. Недавно я прочитал о Currying, очевидном фундаменте языка.
В соответствии с F # для удовольствия и прибыли при создании следующей функции:
let addItems x y = x + y
Что действительно происходит, есть две отдельные функции аргументов, которые создаются.
let addItems x =
let subFunction y =
x + y
subFunction
и когда вы вызываете функцию с помощью addItems 5 6, порядок операций выглядит следующим образом
Все это звучит нормально на поверхности. Однако, когда вы смотрите на IL для этого, он рассказывает другую историю.
.method public static int32 testCurry(int32 x,
int32 y) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )
// Code size 5 (0x5)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add
IL_0004: ret
} // end of method Sandbox::testCurry
В IL можно четко видеть, что создается одна статическая функция, которая принимает два аргумента и возвращает Int32.
Итак, мой вопрос в том, почему расхождение? Это не первый раз, когда я видел ИЛ, который не джив с документацией...
Ответы
Ответ 1
Итак, мой вопрос в том, почему расхождение?
Фактически скомпилированный IL не должен и не должен иметь значения с точки зрения поведенческого контракта. Комбинируя одну функцию, вызов получает значительно лучшую оптимизацию на уровне JIT/runtime.
"Что на самом деле происходит здесь..." не обязательно то, что на самом деле происходит, это больше "как это должно быть объяснено при написании и использовании кода F #...". Основная реализация должна быть бесплатной для изменения по мере необходимости, чтобы наилучшим образом использовать среду выполнения.