0

我正在尝试为没有参数的函数实现定期记忆。

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的新实现。但是,我将最初选择的引用更改为可变引用。我认为这样更有效率。

4

1 回答 1

1

每次调用该函数时,变量都会被重置 - 您需要将它们移到函数之外,例如

type Memoize() =
    let cache = ref 0
    let version = ref 0
    member this.m f =

        let returnValue() =
            if !version = superVersion then
                !cache
            else
                System.Console.WriteLine(!cache)
                cache := f()
                System.Console.WriteLine(!cache)
                version := superVersion
                !cache
        returnValue()
于 2013-03-15T02:21:40.703 回答