首页 文章

关闭特定功能的FSharp功能缓存?

提问于
浏览
2

我最近遇到了一个有趣但恼人的F Sharp行为 . 根据[1],“F#自动缓存任何不带参数的函数的值 . ”这似乎是一个好主意,但是当我尝试提出一个包装函数来生成随机数时,它会给我带来麻烦 .

作为一个例子,我在这个问题的最后代码中有两个不同的函数 . 第一个函数“getRand”不带参数,但不幸的是它总是返回相同的数字 . 第二个函数“getRand2”正如我希望每次调用时生成一个新的随机数一样,但它烦人地占用了一个无用且忽略的额外参数 .

如果可能的话,我想拥有getRand2的功能但是getRand的便利性 . 是否有一个编译器指令或特殊关键字我可以应用于getRand,它将关闭其功能缓存功能,从而使其行为像getRand2?

谢谢,

肖恩
注意:如果答案已经出现在[1]中,请原谅我,我现在还没有看到 .
[1] - http://en.wikibooks.org/wiki/F_Sharp_Programming/Caching

(* Always returns the same number *)
let getRand = 
   let seed = int32(System.DateTime.Now.Ticks)   
   let randGen = new System.Random(seed)
   randGen.Next()

(* Works as expected except I need an annoying extra parameter *)
let getRand2 dummyParam = 
   let seed = int32(System.DateTime.Now.Ticks)   
   let randGen = new System.Random(seed)
   randGen.Next()

(* Outputs three "identical" numbers to console *)
System.Console.WriteLine(
   "Parameterless getRand always outputs same number.")
System.Console.WriteLine(getRand)
System.Threading.Thread.Sleep(100)
System.Console.WriteLine(getRand)
System.Threading.Thread.Sleep(100)
System.Console.WriteLine(getRand)
System.Console.WriteLine()

(* Outputs three "different" numbers to console *)
System.Console.WriteLine(
   "GetRand2 works as expected even though second dummy param is always the same.")
System.Console.WriteLine(getRand2 0)
System.Threading.Thread.Sleep(100)
System.Console.WriteLine(getRand2 0)
System.Threading.Thread.Sleep(100)
System.Console.WriteLine(getRand2 0)
System.Console.WriteLine()

1 回答

  • 6

    为了澄清一下,我认为短语"function which takes no parameters"具有误导性 . 根据定义,函数映射函数's domain to a value in the function' s范围中的值,因此所有函数都采用参数 . 在您的情况下, getRand 未绑定到函数,它只是 int 类型的值 .

    如果我理解你的问题,我想你想做

    let getRand =    
        let seed = int System.DateTime.Now.Ticks      
        let randGen = new System.Random(seed)   
        fun () -> randGen.Next()
    

    您仍然需要将 getRand 作为函数调用( getRand() ,而不仅仅是 getRand ),但是没有办法解决这个问题 - int 值始终保持不变这一事实是推理程序的关键特性 .

    您可以使用 getRand2 函数,就像我的 getRand 版本一样:因为您不在主体内使用 dummyParam ,F#使函数通用,这意味着您可以传递单位值 () 作为参数 . However ,你的 getRand2 函数被破坏,因为它每次调用时都会创建一个新的随机数生成器 . 这意味着如果你在一个刻度内调用它两次,你将得到相同的答案:

    let x,y = (getRand2(), getRand2())
    

    那个's why it'重要的是在匿名函数范围之外定义 seedrandGen .

相关问题