F#正确使用序列缓存

时间:2009-06-29 20:56:52

标签: caching f# sequence primes

我正在尝试将Seq.cache与我所做的函数一起使用,该函数返回一个数字序列,最多为数字N,不包括数字1.我无法弄清楚如何将缓存序列保留在范围内但是仍然在我的定义中使用它。

let rec primesNot1 n = 
    {2 .. n} 
    |> Seq.filter (fun i -> 
        (primesNot1 (i / 2) |> Seq.for_all (fun o -> i % o <> 0)))
    |> Seq.append {2 .. 2}
    |> Seq.cache

关于如何使用Seq.cache来加快速度的任何想法?目前它不断从范围中退出,只会降低性能。

3 个答案:

答案 0 :(得分:10)

Seq.cache缓存IEnumerable<T>实例,以便序列中的每个项目仅计算一次。但是,在您的情况下,您正在缓存函数返回的序列,并且每次调用该函数时都会得到 new 缓存序列,这对您没有任何帮助。我不认为缓存是你正确解决问题的正确方法;相反,你应该考虑记忆。

如果不是定义一个给出小于n的素数的函数,而是想要定义一个无限可枚举的素数序列,那么缓存就更有意义了。这看起来更像是这样:

let rec upFrom i =
  seq { 
    yield i
    yield! upFrom (i+1)
  }

let rec primes =
  seq { 
    yield 2
    yield!
      upFrom 3 |>
      Seq.filter (fun p -> primes |> Seq.takeWhile (fun j -> j*j <= p) |> Seq.forall (fun j -> p % j <> 0))
  }
  |> Seq.cache

我没有比较这种方法与你的相比。

答案 1 :(得分:2)

我想出了如何用折叠来解决我的问题但不是我使用seq.cache的想法。

let primesNot1 n = 
    {2 .. n}
    |> Seq.fold (fun primes i ->
        if primes |> Seq.for_all (fun o -> i % o <> 0) then
            List.append primes [i]
        else
            primes) [2]

答案 2 :(得分:2)

你看过LazyList吗?似乎它旨在解决同样的问题。它在PowerPack中。