Играя с F# във VS2010 beta2 и тъй като съм нов в F#, просто избрах един от често срещаните примери и продължих напред и внедрих факторна функция като:
let rec factorial n =
if n <= 1 then 1 else n * factorial (n - 1);;
Ако създам това и погледна генерирания код в Reflector, получавам съответния C# код:
public static int Factorial(int n) {
if (n <= 1)
return 1;
return n * Factorial(n - 1);
}
Така че, ако компилирам C# представянето на F# кода на Reflector, очаквам да получа идентичен IL.
Въпреки това, ако компилирам и двата фрагмента в режим на освобождаване и сравня генерирания IL, те са различни (те са функционално идентични, но все още се различават малко).
Реализацията на C# се компилира до:
.method public hidebysig static int32 Factorial(int32 n) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: bgt.s L_0006
L_0004: ldc.i4.1
L_0005: ret
L_0006: ldarg.0
L_0007: ldarg.0
L_0008: ldc.i4.1
L_0009: sub
L_000a: call int32 TestApp.Program::Factorial(int32)
L_000f: mul
L_0010: ret
}
Реализацията на F# се компилира до:
.method public static int32 factorial(int32 n) cil managed
{
.maxstack 5 <=== Different maxstack
L_0000: nop <=== nop instruction?
L_0001: ldarg.0
L_0002: ldc.i4.1
L_0003: bgt.s L_0007
L_0005: ldc.i4.1
L_0006: ret
L_0007: ldarg.0
L_0008: ldarg.0
L_0009: ldc.i4.1
L_000a: sub
L_000b: call int32 FSharpModule::factorial(int32)
L_0010: mul
L_0011: ret
}
Генерираният код е идентичен с изключение на различния maxstack и допълнителната инструкция NOP в метода F#.
Това вероятно не е важно, но съм любопитен защо F# компилаторът ще вмъкне NOP в версия на версия.
Може ли някой да обясни защо?
(Напълно съм наясно, че F# компилаторът не е преминал през същото ниво на тестване в реалния свят като C# компилатора, но това е толкова очевидно, че си представям, че щеше да бъде уловено).
РЕДАКТИРАНЕ: Командата за компилиране е както следва
C:\Program Files\Microsoft F#\v4.0\fsc.exe -o:obj\Release\FSharpLib.dll
--debug:pdbonly --noframework --define:TRACE --optimize+
--target:library --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths
--flaterrors "C:\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.fs" Module1.fs
(референтните модули са премахнати за краткост).