2013-03-15 90 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