我正在尝试为没有参数的函数实现定期记忆。
let mutable superVersion = 1
type Memoize() =
member this.m f =
let cache = ref 0
let version = ref 0
let returnValue() =
if !version = superVersion then
!cache
else
System.Console.WriteLine(!cache)
cache := f()
System.Console.WriteLine(!cache)
version := superVersion
!cache
returnValue()
let simpleFunction() = 10 + 5 // Could be some mutable data here
let aFunction() =
let Mem = new Memoize()
let myFunc() = simpleFunction() + 1
Mem.m myFunc
这个想法很简单。当数据进入这个程序时,superVersion 增加 1。这样所有函数都必须重新计算,但只有当新数据进入时。之后,许多后面的函数可以建立在早期的函数上,并且永远不会重新计算早期的函数。这样就不需要任何事件。
现在我对编程尤其是 F# 非常陌生。所以我不知道,在彼此之上构建大量这些函数会导致堆栈溢出或其他什么吗?
我要做的只是数据研究,而不必担心使用事件或其他东西以正确的顺序计算事物。有点像 excel,除了 excel 走得更远,只在链接中的前一个单元格(依赖项)发生变化时计算。
所以我希望能得到一些关于这个问题的信息。但是,现在进入主要问题:
然后当我调用 aFunction() 时,版本和缓存都会被计算出来,然后重置为 0。你可以看到我已经放置了 2 个控制台写行。第一个值为 0,第二个值为 16。再次调用 aFunction(不更改 superVersion),我得到完全相同的结果,而不是两者都得到 16。为什么缓存重置回0?
非常感谢。
编辑:就像我选择的答案让我知道,我真的忘记了函数的作用。他们在使用时会调用自己的身体。所以一切都在他们身上重置。我太专注于他们应该在哪里实现一个类。
我想要做的正确实现是这样的:
type Cell(f) =
let mem = Memoize()
let _Value() = mem.m f
member this.Value = _Value()
现在对于每个函数,或者我现在所说的,单元格。我只需创建一个新的单元格实例并传入我想要的计算(一个函数)。现在因为我在上课,所以 Memoize() 只被创建一次并且它的状态被保存了。使用在 John Palmer 的回答中看到的 Memoize的新实现。但是,我将最初选择的引用更改为可变引用。我认为这样更有效率。