von this question Entstanden, habe ich dieses kleine F # -Code (github) Zufallswerte zu erzeugen, gemäß einer Normalverteilung:Stack-Überlauf trotz Position Endaufruf aber nur in 64-Bit-
// val nextSingle : (unit -> float32)
let nextSingle =
let r = System.Random()
r.NextDouble >> float32
// val gauss : (float32 -> float32 -> seq<float32>)
let gauss mean stdDev =
let rec gauss ready = seq {
match ready with
| Some spare ->
yield spare * stdDev + mean
yield! gauss None
| _ ->
let rec loop() =
let u = nextSingle() * 2.f - 1.f
let v = nextSingle() * 2.f - 1.f
let s = pown u 2 + pown v 2
if s >= 1.f || s = 0.f then loop() else
u, v, s
let u, v, s = loop()
let mul = (*)(sqrt(-2.f * log s/s))
yield mul u * stdDev + mean
yield! mul v |> Some |> gauss
}
gauss None
Ich scheint es, dass Dieser sollte sich nur in Tail-Call-Position aufrufen, ergo nie einen StackOverflowException
verursachen, wenn TCO aktiviert ist. Aber es tut beim Ausführen 64-Bit. Es nicht beim Ausführen 32-Bit (d. H. "Prefer 32-Bit" Kontrollkästchen in den Projekteinstellungen).
Ich verwende .NET Framework 4.5.2 und F # 4.4.0.0.
Kann jemand erklären, was das Problem verursacht?
Welche .NET-Version verwenden Sie? – Roujo
Ich fand diese Artikel über die Optimierung von Endanrufen [unter Verwendung von .NET 2.0] (https://blogs.msdn.microsoft.com/davbr/2007/06/20/tail-call-jit-conditions/) vs. [using. NET 4.0] (https://blogs.msdn.microsoft.com/clrcodegeneration/2009/05/11/tail-call-improvements-in-net-framework-4/), vielleicht können sie helfen. – Roujo
Auch welche Version von F # benutzt du? Ich benutze F # 4 und beim Debuggen sehe ich keinen Stapel wachsen. Ich zerlegte den IL-Code und es sieht so aus, als ob der Code F # 4 nicht stackoverflow generieren sollte. – FuleSnabel