gram z F # w VS2010 beta2, a ponieważ jestem nowy F #, po prostu wybrał jeden z typowych przykładów i poszedł do przodu i wdrożył funkcję silni jak:NOP w wersji kompilacji F # Kod
let rec factorial n =
if n <= 1 then 1 else n * factorial (n - 1);;
Jeśli buduję ten i patrzeć na wygenerowanego kodu w reflektor, pojawia się odpowiedni kod C#:
public static int Factorial(int n) {
if (n <= 1)
return 1;
return n * Factorial(n - 1);
}
Więc jeśli mogę skompilować reflektor w C# reprezentację kod F #, chciałbym oczekiwać, aby uzyskać identyczną IL.
Jednakże, jeśli skompiluję oba te fragmenty w trybie zwolnienia i porównam wygenerowaną IL, są one różne (są funkcjonalnie identyczne, ale wciąż nieco różnią się).
C realizacja # kompiluje do:
.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
}
the # wdrożenie F kompiluje do:
.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
}
Wygenerowany kod jest identyczny z wyjątkiem innego maxstack oraz dodatkowych instrukcji NOP w # metody F.
To prawdopodobnie nie jest znaczące, ale jestem ciekawy, dlaczego kompilator F # wstawił NOP w kompilacji wydania.
Czy ktoś może wyjaśnić, dlaczego?
(Jestem w pełni świadomy, że kompilator F # nie przeszedł tego samego poziomu testów w świecie rzeczywistym, co kompilator języka C#, ale jest to tak oczywiste, że obraz zostałby przechwycony).
Edycja: Polecenie kompilacji następująco
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
(zespoły użyte usunięte dla uproszczenia).
Cóż, używam domyślnego profilu kompilacji "release" w VS2010, więc zakładam, że faktycznie buduję w trybie zwolnienia. Okno wyjściowe mówi "Rozpoczęto kompilację: Projekt: FSharpLib, Konfiguracja: Zwolnij dowolny procesor". Jeśli zmienię na "debugowanie", otrzymuję zupełnie inny MSIL zgodnie z oczekiwaniami. –
Testuję używając F # 1.9.7.8 i wiersza poleceń. Jeśli nie przekażę/debuguję, nie dostanę nop. –
Zaktualizowałem pytanie za pomocą wiersza poleceń do kompilacji i próbowałem skompilować bezpośrednio za pomocą fsc.exe. Ten sam wynik. Według okna wyjściowego VS2010b2 nie jest dostarczany z najnowszym kompilatorem, ponieważ zgłasza numer wersji F # w wersji 1.9.7.4. Czy to może być różnica? –