关闭特定函数的 FSharp 函数缓存?

发布于 2024-11-18 07:09:11 字数 1668 浏览 2 评论 0原文

我最近遇到了一个有趣但令人讨厌的 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()

I recently ran into an interesting but annoying F Sharp behavior. According to [1], “F# automatically caches the value of any function which takes no parameters.” This seems like a good idea, but it is causing problems for me as I try to come up with a wrapper function to generate random numbers.

As an example, I have two different functions in the code at the end of this question. The first function “getRand” takes no parameters, but unfortunately it always returns the same number. The second function “getRand2” works as I would expect generating a new random number each time it is called, but it annoyingly takes a useless and ignored extra parameter.

If possible, I would like to have the functionality of getRand2 but the convenience of getRand. Is there a compiler directive or special keyword I can apply to getRand that will turn off its function caching capabilities and thereby cause it to behave like getRand2?

With Thanks,

Shawn
Note: Forgive me if the answer already appears in [1], I’m just not seeing it right now.
[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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯寂 2024-11-25 07:09:11

只是为了澄清一下,我认为“不带参数的函数”这个短语具有误导性。根据定义,函数将函数域中的值映射到函数范围内的值,因此所有函数都采用参数。在您的情况下,getRand 未绑定到函数,它只是一个int 类型的值。

如果我正确理解你的问题,我认为你想做的

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

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

您可以按照与我的 getRand 版本大致相同的方式使用 getRand2 函数:因为您不在正文中使用 dummyParam,F#使函数变得通用,这意味着您可以根据需要将单位值 () 作为参数传递。 但是,您的 getRand2 函数已损坏,因为它每次调用时都会创建一个新的随机数生成器。这意味着,如果您在一个周期内调用它两次,您将得到相同的答案:

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

这就是为什么定义 seedrandGen outside 很重要匿名函数的范围。

Just to clarify a bit, I think that the phrase "function which takes no parameters" is misleading. By definition, a function maps a value from the function's domain to a value in the function's range, so all functions take parameters. In your case, getRand is not bound to a function, it's just a value of type int.

If I understand your question correctly, I think you want to do

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

You still need to call getRand as a function (getRand(), not just getRand), but there's no way to work around this - the fact that an int value always remains the same is a critical feature for reasoning about a program.

You could use your getRand2 function in much the same way as my version of getRand: since you don't use dummyParam within the body, F# makes the function generic, which means that you can pass the unit value () as the argument if you want. However, your getRand2 function is broken, in that it creates a new random number generator each time it is called. This means that if you call it twice within one tick, you will get the same answer:

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

That's why it's important to define seed and randGen outside of the scope of the anonymous function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文