为什么这些值重置为0?

时间:2013-03-15 02:03:50

标签: f#

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

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个控制台writelines。在第一个中,值为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的 new 实现。但是我将我最初选择的引用更改为mutables。我认为这更有效率。

1 个答案:

答案 0 :(得分: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()