我最近遇到了一个有趣但令人讨厌的F Sharp行为.根据[1],"F#自动缓存任何不带参数的函数的值."这似乎是一个好主意,但是当我试图想出一个包装函数来生成随机数时,它会给我带来麻烦.
作为一个例子,我在这个问题的最后代码中有两个不同的函数.第一个函数"getRand"不带参数,但不幸的是它总是返回相同的数字.第二个函数"getRand2"正如我希望每次调用时生成一个新的随机数一样,但它烦人地占用了一个无用且忽略的额外参数.
如果可能的话,我想拥有getRand2的功能但是getRand的便利性.是否有一个编译器指令或特殊关键字我可以应用于getRand,它将关闭其功能缓存功能,从而使其行为像getRand2?
谢谢,
Shawn
注意:如果答案已经出现在[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()
Run Code Online (Sandbox Code Playgroud)
为了澄清一点,我认为短语"不带参数的功能"是误导性的.根据定义,函数将函数域中的值映射到函数范围中的值,因此所有函数都接受参数.在你的情况下,getRand没有绑定到一个函数,它只是一个类型的值int.
如果我理解你的问题,我想你想做
let getRand =
let seed = int System.DateTime.Now.Ticks
let randGen = new System.Random(seed)
fun () -> randGen.Next()
Run Code Online (Sandbox Code Playgroud)
你仍然需要getRand作为一个函数调用(getRand()不仅仅是getRand),但是没有办法解决这个问题 - int值始终保持不变这一事实是推理程序的关键特性.
你可以getRand2像我的版本一样使用你的函数getRand:因为你没有dummyParam在体内使用,所以F#使函数通用,这意味着你可以根据需要传递单位值()作为参数. 但是,您的getRand2功能被破坏,因为它每次调用时都会创建一个新的随机数生成器.这意味着如果你在一个刻度内调用它两次,你将得到相同的答案:
let x,y = (getRand2(), getRand2())
Run Code Online (Sandbox Code Playgroud)
这就是为什么它重要的是要确定seed和randGen 外面的匿名函数的范围.
| 归档时间: |
|
| 查看次数: |
398 次 |
| 最近记录: |