f# - Desbordamiento de pila a pesar de la posición de llamada de cola, pero solo en 64 bits
64bit stack-overflow (1)
Parece un error en el mecanismo de compilación de la expresión de la secuencia del compilador. Aquí hay una reproducción simplificada:
let rec loop r = seq {
if r > 0 then
let rec unused() = unused()
yield r
yield! loop r
}
printfn "%i" (Seq.nth 10000000 (loop 1))
Obviamente, la presencia de la definición recursiva no utilizada no debería afectar si esto genera un desbordamiento de la pila, pero lo hace.
Originado a partir de esta pregunta , tengo este pequeño código F # ( github ) para generar valores aleatorios de acuerdo con una distribución normal:
// 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
Para mí, parece que esto solo debería llamarse a sí mismo en la posición de llamada final, ergo nunca causar una StackOverflowException
cuando TCO está habilitado. Pero lo hace cuando se ejecuta 64 bits . No funciona cuando se ejecuta la casilla de 32 bits (es decir, "Prefiere 32 bits" en la configuración del proyecto).
Estoy usando .NET Framework 4.5.2 y F # 4.4.0.0.
¿Alguien puede explicar qué está causando el problema?