views:

323

answers:

3

I'm trying to use Seq.cache with a function that I made that returns a sequence of primes up to a number N excluding the number 1. I'm having trouble figuring out how to keep the cached sequence in scope but still use it in my definition.

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

Any ideas of how I could use Seq.cache to make this faster? Currently it keeps dropping from scope and is only slowing down performance.

+4  A: 

Seq.cache caches an IEnumerable<T> instance so that each item in the sequence is only calculated once. In your case, though, you're caching the sequence returned by a function, and each time you call the function you get a new cached sequence, which doesn't do you any good. I don't think caching is really the right approach to your problem as you've outlined it; instead you should probably look into memoization.

If instead of defining a function giving the primes less than n you want to define an infinite enumerable sequence of primes, then caching makes more sense. That would look more like this:

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

I haven't compared the performance of this method compared to yours.

kvb
Awesome thanks, performance is good.
gradbot
A: 

I figured out how to solve my problem with a fold but not my idea of using 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]
gradbot
Performance is about 3x better with fold using the old September release. I'll check in vs2010 later today.
gradbot
Performance in VS2010 is 2x better with the fold. Nice to know there was a increase in the performance of sequences.
gradbot
A: 

Have you taken a look at LazyList? Seems like it's designed to solve the same problem. It's in PowerPack.

James Moore