在下面的函數中,我試圖通過使用累加器來設置尾遞歸。但是,我遇到了堆棧溢出異常,這導致我相信我設置函數的方式不能正確啓用尾部遞歸。F#使用累加器,仍然出現堆棧溢出異常
//F# attempting to make a tail recursive call via accumulator
let rec calc acc startNum =
match startNum with
| d when d = 1 -> List.rev (d::acc)
| e when e%2 = 0 -> calc (e::acc) (e/2)
| _ -> calc (startNum::acc) (startNum * 3 + 1)
這是我的理解是使用acc
讓編譯器,看看有沒有必要繼續圍繞每一個遞歸調用所有的棧幀,因爲它可以東西,在ACC每遍的結果,每幀返回。顯然,我不明白如何正確使用累加器值,因此編譯器會調用尾調用。
如果在單聲道這樣做,你的運氣了,因爲單不優化尾調用的是,即使是F#。 – 2010-11-06 01:30:01
我沒有Mono系統來檢查它,但是在Windows .NET下查看反射輸出顯示tailcall優化* *已經針對該版本進行了優化。 – TechNeilogy 2010-11-06 01:37:46
你的函數是正確的尾遞歸。如果您使用Visual Studio並在調試模式下編譯,尾遞歸將默認關閉(以啓用更好的調試體驗):http://stackoverflow.com/questions/1416415/f-stackoverflow-project-euler-4 – 2010-11-06 01:39:24