缓存函数结果f#

时间:2009-12-29 20:15:35

标签: caching 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

但我认为我深深地错了。对于函数式语言来说,缓存这样的结果必须是非常常见和简单的事情。

2 个答案:

答案 0 :(得分:3)

这是关于这个主题的thorough thread

这是Internet Archive链接。

答案 1 :(得分: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。它采用非curried函数并返回另一个具有相同签名的函数。给定的函数仅对传递给它的每个唯一参数调用一次。这使它适用于昂贵的纯功能。但是,此缓存功能不是纯粹的,也不是线程安全的。以下是其用法示例:

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

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

第一次调用时,调用fast 1会导致第二次睡眠。每个具有相同参数的连续调用将立即返回值。