Почему F # не компилирует Currying в отдельные функции?

Итак, я пытаюсь изучить F #, и, изучая новые вещи, мне нравится смотреть на IL, чтобы увидеть, что происходит под обложками. Недавно я прочитал о Currying, очевидном фундаменте языка.

В соответствии с F # для удовольствия и прибыли при создании следующей функции:

let addItems x y = x + y

Что действительно происходит, есть две отдельные функции аргументов, которые создаются.

let addItems x =
    let subFunction y = 
          x + y
    subFunction

и когда вы вызываете функцию с помощью addItems 5 6, порядок операций выглядит следующим образом

  • addItems вызывается с аргументом 5

  • addItems возвращает subFunction

  • subFunction вызывается с аргументом 6
  • subFunction имеет аргумент 5 в области видимости, поэтому он добавляет и возвращает сумму 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 #...". Основная реализация должна быть бесплатной для изменения по мере необходимости, чтобы наилучшим образом использовать среду выполнения.