9

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

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 来加快速度的任何想法?目前,它一直在范围内下降,并且只会降低性能。

4

3 回答 3

11

Seq.cache缓存一个IEnumerable<T>实例,以便序列中的每个项目只计算一次。但是,在您的情况下,您正在缓存函数返回的序列,并且每次调用该函数时都会得到一个的缓存序列,这对您没有任何好处。正如您所概述的那样,我认为缓存并不是解决问题的正确方法;相反,您可能应该研究记忆。

如果不是定义一个函数给出的素数少于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

我没有将这种方法的性能与您的方法进行比较。

于 2009-06-29T21:13:40.563 回答
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]
于 2009-06-29T21:48:27.497 回答
2

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

于 2009-06-30T22:43:16.010 回答