F#中的递归函数与递归变量

时间:2012-07-01 20:11:03

标签: recursion f#

第一种方法是OK。 第二个不断重复相同的数字。

对我而言,这是非常模糊的......你能指出好的方向吗?

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

2 个答案:

答案 0 :(得分:4)

在第一个样本randomNormal()是一个函数,它需要()并返回一个值,每次都会对它进行评估。 在第二个randomNormal是一个值,所以它不会被评估两次,一旦有界,它将保持相同的值。

如果翻转randomNormal()签名是:

unit->seq<float>

randomNormal只是:

seq<float>

更新:它保持打印,因为printfn在序列内,这是有界值。 如果您尝试在最后一行之前在身体中打印,您将看到差异。这是一个简化的示例代码:

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

答案 1 :(得分:0)

完成Gustavo的回答,randomNormal是一个值,在由解释器计算后,绑定到一个序列。

randomNormal的进一步调用将产生此序列,并且在序列之前使用的绑定没有理由被评估。 t,theta等...将始终具有相同的值。 什么是 ,但序列将被评估,因此打印。

randomNormal()的情况下,同样的情况发生,但是评估绑定,因为函数可能依赖于副作用。