最近,我遇到了有趣但烦人的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()

最佳答案

只是为了澄清一下,我认为“不带参数的函数”这一短语具有误导性。根据定义,函数会将值从函数的域映射到函数范围内的值,因此所有函数都带有参数。在您的情况下,getRand没有绑定(bind)到函数,它只是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#使该函数具有通用性,这意味着您可以根据需要将单位值()作为参数传递。 但是,您的getRand2函数已损坏,因为它在每次调用时都会创建一个新的随机数生成器。这意味着,如果在一个刻度内两次调用它,您将得到相同的答案:
let x,y = (getRand2(), getRand2())

这就是为什么在匿名函数范围之外定义seedrandGen如此重要的原因。

关于f# - 是否为特定功能关闭FSharp功能缓存?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6554933/

10-10 20:56