我想知道这是一个错误还是我做错了什么。我在mono / linux中运行F#,以下代码崩溃,给我一个没有任何堆栈跟踪的堆栈溢出。
let rec gcd a b =
match b with
| x when x = 0 -> a
| _ -> gcd b (a%b)
let z = (gcd 12 3)
printfn "%A" z
当我在REPL中运行相同的代码时,这可以正常工作。
有趣的是,这很好用
let rec gcd a b =
match b with
| x when x = 0 -> a
| _ -> gcd b (a%b)
printfn "%A" (gcd 12 3)
修改
尝试--optimize解决方案并没有帮助,有趣的是我发现遵循John Palmer的建议并用x when x = 0
替换0
工作,但是当尝试相同的技术时使用int64
,0L
再次给我相同的堆栈溢出。我不知道这是一个尾部优化问题,因为3是堆栈深度低的12倍。除非别人可以告诉我这里发生了什么,否则我把它作为一个错误。
答案 0 :(得分:3)
一般情况下,fsi通常设置为使用--optimize
(在Visual Studio中的Windows上,不确定单声道)。
因此,REPL将应用尾调用,但未经优化的编译应用程序将不会。您可以通过使用fsharpc --optimize+ ...
另外,改变
|x when x = 0
到
|0
编辑:我认为这可能实际上是编译器/单声道错误 - 在任何地方添加printf都可以摆脱它。
反编译版本:
虫:
IL_0000: ldarg.1
IL_0001: brtrue.s IL_0005
IL_0003: ldarg.0
IL_0004: ret
IL_0005: ldarg.1
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: rem
IL_0009: starg.s 1
IL_000b: starg.s 0
IL_000d: br.s IL_0000
并且很好:
IL_0000: ldarg.1
IL_0001: switch (
IL_0014)
IL_000a: ldarg.1
IL_000b: ldarg.0
IL_000c: ldarg.1
IL_000d: rem
IL_000e: starg.s 1
IL_0010: starg.s 0
IL_0012: br.s IL_0000
IL_0014: ldarg.0
IL_0015: ret
对我来说,没什么好看的。
我正在运行mono 3.2.8和一个相当现代的F#编译器 - 当我有时间重新编译编译器时,我将测试最新的git。