问题
The first method is OK. The second repeats constantly the same pair of numbers.
It is quite obscure to me why... Could you point to the good direction ?
module Normal =
let rnd = new MersenneTwister()
let sampleNormal =
fun () -> let rec randomNormal() = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2
seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal() }
randomNormal()
let sampleNormalBAD =
fun () -> let rec randomNormal = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2
seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal }
randomNormal
Normal.sampleNormal() |> Seq.take(10) |>Seq.toArray
Normal.sampleNormalBAD() |> Seq.take(10) |>Seq.toArray
回答1:
In the first sample randomNormal()
is a function, it takes ()
and return a value, it will be evaluated each time.
In the second one randomNormal
is a value, so it will not be evaluated twice, once bounded it will remain with the same value.
If you rollover randomNormal()
the signature is :
unit->seq<float>
and for randomNormal
is just :
seq<float>
UPDATE: It keeps printing because the printfn
is inside the sequence, which is the bounded value.
If you try printing in the body before the last line you will see the difference. Here's a simplified sample code:
let sampleNormal =
fun () ->
let rec randomNormal() =
let u1, u2 = 1,2
printfn "Evaluating"
seq { yield u1; yield u2 ; printfn "next";yield! randomNormal() }
randomNormal()
let sampleNormalBAD =
fun () ->
let rec randomNormal =
let u1, u2 = 1,2
printfn "Evaluating"
seq { yield u1; yield u2 ; printfn "next";yield! randomNormal }
randomNormal
回答2:
Completing Gustavo's answer, randomNormal
is a value and after being computed by the interpreter, is bound to a sequence.
Further calls to randomNormal
will yield this sequence, and the bindings used before the sequence have no reason to be evaluated. t, theta etc.. will always have the same value.
What is inside the sequence will be evaluated though, hence the print.
In the case of randomNormal()
the same happens, but the bindings are evaluated, as function might be relying on side effects.
来源:https://stackoverflow.com/questions/11285286/recursive-function-vs-recursive-variable-in-f