我在VS2010 Beta2中使用f,由于我对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);
}
所以如果我编译reflector的f代码的c表示,我会得到相同的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和f方法中附加的nop指令。
这可能并不重要,但我很好奇为什么f编译器会在发布版本中插入nop。
谁能解释为什么?
(我非常清楚f编译器并没有经历与c编译器相同的实际测试级别,但这一点非常明显,我认为它会被捕获)。
edit:compile命令如下
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
(为简洁起见,删除了引用的程序集)。