Caching F#正确使用序列缓存
我正在尝试将Seq.cache与我创建的一个函数一起使用,该函数返回一个素数序列,该序列的最大值为N,不包括1。我很难弄清楚如何保持缓存序列在作用域中,但仍在定义中使用它Caching F#正确使用序列缓存,caching,f#,sequence,primes,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))) |> Se
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
让rec primesNot1 n=
{2..n}
|>顺序过滤器(趣味i->
(primesNot1(i/2)|>Seq.for_all(fun o->i%o 0)))
|>Seq.append{2..2}
|>Seq.cache
有没有关于如何使用Seq.cache加快速度的想法?目前,它不断从作用域中删除,只会降低性能。
Seq.cache
缓存一个IEnumerable
实例,以便序列中的每个项只计算一次。但是,在您的例子中,您正在缓存一个函数返回的序列,每次调用该函数时都会得到一个新的缓存序列,这对您没有任何好处。我认为缓存并不是解决问题的正确方法,正如您所概述的那样;相反,你可能应该研究一下备忘录
如果您不想定义一个素数小于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
让rec从i开始=
序号{
产量一
屈服!从(i+1)向上
}
设rec素数=
序号{
收益率2
产量
从3|>
Seq.filter(fun p->primes |>Seq.takeWhile(fun j->j*j Seq.forall(fun j->p%j 0))
}
|>Seq.cache
我还没有将此方法的性能与您的方法进行比较。我找到了使用fold解决问题的方法,但没有想到使用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]
let primesNot1 n=
{2..n}
|>顺序折叠(趣味素数i->
如果素数|>Seq.for_all(fun o->i%o 0),那么
List.append素数[i]
其他的
素数[2]
你看过LazyList了吗?似乎它是为了解决同样的问题而设计的。它在PowerPack中。使用旧的9月份版本时,fold的性能大约提高了3倍。我今天晚些时候会查看vs2010。vs2010的性能是fold的2倍。很高兴知道序列的性能有所提高。