Я играю с F # в VS2010 бета2, и так как я новичок в F #, я просто выбрал один из распространенных примеров и пошел вперед и реализовали функцию факториала как:NOP в релиз сборки F # код
let rec factorial n =
if n <= 1 then 1 else n * factorial (n - 1);;
Если я строю это и посмотреть на сгенерированный код в отражатель, я получаю соответствующий C# код:
public static int Factorial(int n) {
if (n <= 1)
return 1;
return n * Factorial(n - 1);
}
Так что, если я скомпилировать C# представление рефлектора из F # код, я бы ожидать, чтобы получить идентичную 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#, но это настолько очевидно, что я бы его поймал).
EDIT: Команда компиляции выглядит следующим образом
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
(ссылочные узлы удалены для краткости).
Ну, я использую профиль сборки «release» по умолчанию в VS2010, поэтому я бы предположил, что я на самом деле строю в режиме выпуска. В окне вывода говорится: «Сборка запущена: проект: FSharpLib, Configuration: Release Any CPU». Если я перейду на «отладку», я получу совершенно другой MSIL, как ожидалось. –
Я тестирую с использованием F # 1.9.7.8 и командной строки. Если я не пройду/отлаживаю, я не получу нуль. –
Я обновил вопрос с помощью командной строки для компиляции, и я попытался скомпилировать с помощью fsc.exe напрямую. Тот же результат. Согласно выходному окну VS2010b2 не поставляется с последним компилятором, поскольку он сообщает номер версии F # версии 1.9.7.4. Разве может быть разница? –