2013-03-15 110 views
0

我正在试图为没有参数的函数实现定期记忆。为什么这些值重置为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更进一步,只有当链接中的前一个单元格(依赖关系)发生变化时才计算。

所以我希望能得到关于这个问题的一些信息。然而,现在到主要问题:

当我然后调用函数(),版本和缓存得到计算,然后重置为0.您可以看到我已经放置了2个控制台writelines。第一个值是0,第二个是16.再次调用函数(不改变superVersion),我得到完全相同的结果,而不是在两个都得到16。为什么高速缓存重置为0?

非常感谢。

编辑:就像我选择让我知道答案,我真的忘了什么功能做。他们在使用时称他们的身体。所以一切都在他们重置。我太专注于他们应该实施课程的地方。

为我想要做会去这样的事情是什么的正确实施:

type Cell(f) = 
    let mem = Memoize() 
    let _Value() = mem.m f 
    member this.Value = _Value() 

现在,每一个功能,或者我打电话,现在,细胞。我只是创建一个新的单元格实例,并通过我想要的计算(一个函数)。现在因为我在一个类中,Memoize()只创建一次,其状态被保存。使用新的执行Memoize在约翰帕尔默的答案中看到。然而我改变了我最初选择的可变参考。我认为这样更有效率。

+0

噢人,我很尴尬。这个代码在某处非常愚蠢。我只知道它,也可能是这个想法:P – Dimension 2013-03-15 02:09:55

+0

您现在使用的更新版本是“Lazy <'t>”的几乎精确克隆 - 请参阅http://msdn.microsoft.com/zh-cn/library/dd233247。 aspx – 2013-03-15 20:41:27

+0

这个问题的关键在于能够更改版本并使其重新计算,因为新数据进入并因此使所有内容无效。我不明白懒惰是怎么可能的。它在你所包含的链接中说:“强制执行只执行一次,随后对Force的调用返回相同的结果,但不执行任何代码。” - 但是,谢谢你的信息,这很有趣,我不知道! – Dimension 2013-03-16 00:28:33

回答

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() 
+0

谢谢。我从来没有在c#中犯过这样的错误:P。我想这个过渡让我感到困惑。还有一个问题,调用这样的函数可以创建一个其他函数的树来下移并首先计算。这不会创建一个计算器?我并没有给出这个例子,但我只是指更多的功能实现这个Memoization的东西从别人实施计算。 – Dimension 2013-03-15 02:28:16

+0

只要您明智,创建一个函数层就可以了,在开始达到堆栈大小限制之前,您需要很多层。 – 2013-03-15 02:29:35

+2

@Dimension - 另外,你似乎重新实现了'懒惰<'t>'类型 – 2013-03-15 04:50:18