2009-12-29 143 views
3

我有一個函數,是恆定的以它的參數,例如緩存功能結果f#

let is_prime x = (test) 

但它是相當大的和緩慢的。所以我希望它的結果只需計算一次,而我只是按照自己的需要經常調用它。

我試圖做到這一點的方式我這麼做是不是功能性的語言:

let _is_prime x = (test) 

let mutable _is_prime_primes = [] 
let mutable _is_prime_tested = [] 

let is_prime x = 
    if List.exists (fun el -> el = x) _is_prime_primes then 
     true 
    else 
     if List.exists (fun el -> el = x) _is_prime_tested then 
     false 
    else 
     let result = _is_prime x 
     if result then _is_prime_primes <- x :: _is_prime_primes 
     _is_prime_tested <- x :: _is_prime_tested 
     result 

但是我覺得我深深錯誤。緩存這樣的結果對於函數式語言來說必須是非常普通和簡單的。

+0

看到這個關於memoization的答案:http://stackoverflow.com/questions/833180/handy-f-snippets/851449#851449 – Benjol 2010-01-04 12:53:17

回答

3

這是關於這個問題的thorough thread

這裏是Internet Archive鏈接。

+0

哦,懶惰的初始化。謝謝!它不是一個函數,它是數據,這是點 – 2009-12-29 20:20:59

+1

-1,不應該張貼鏈接作爲答案 - 現在它已經死了。 – ebb 2013-08-20 07:15:01

+0

@ebb這是一個恥辱:(現在刪除答案 – 2013-08-20 09:25:28

1

我在FSI測試中遇到了問題,但它在正常的F#項目中應該沒問題。

let cache f = 
    let dict = new Dictionary<_,_>() 
    fun n -> 
     if dict.ContainsKey(n) then dict.[n] 
     else 
      let r = f n 
      dict.[n] <- r 
      r 

其簽名是('a->'b) -> ('a->'b) when 'a : equality。它採用非curry函數並返回具有相同簽名的另一個函數。給定的函數只對傳遞給它的每個唯一參數調用一次。這使得昂貴的純功能成爲可能。然而,這個緩存功能並不純粹,而且也不是線程安全的。下面是它的用法的例子:

let slow n = // 'a -> 'a 
    System.Threading.Thread.Sleep(1000) 
    n 

let fast = cache slow // 'a -> 'a 

調用fast 1會導致睡眠中的第2第一次調用它。每個具有相同參數的連續調用將立即返回該值。

+0

謝謝!實際上我創建了一個序列並將其放入|> Seq.cache中。你的功能也很棒,謝謝,我會用它來做別的 – 2009-12-31 07:01:26