Wednesday, 14 October 2009

Scala, lazy evaluation and the Sieve of Eratosthenes

I found a Scala algorithm for the Sieve of Eratosthenes here

Since that was written, the #:: object has been added to Stream and can be used instead of Stream.cons. Also as of a recent nightly build, #:: now object works in Stream pattern matching which means the Sieve of Eratosthenes can be even closer to the haskell implementation. (Presumably a good thing as it broadens your choices)


object Primes {

/* Haskell...
primes = sieve [2..]
sieve (p : xs) = p : sieve [x | x <− xs, x `mod` p > 0]
*/

def primes = {
def sieve(is: Stream[Int]): Stream[Int] = is match {
case p #:: xs => p #:: sieve(for (x <- xs if x % p > 0) yield x)
}
sieve(Stream from 2)
}

def main(args: Array[String]) {
primes take 100 foreach println
}
}


Nice!

3 comments:

Landei said...

You should read http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

I translated the solution described in the paper to Scala. It's here:
http://dgronau.wordpress.com/2009/08/30/mit-sieben-sieben-sieben/
(unfortunately my blog is in German)

Daniel said...

To clarify Landei's post, that Haskell code, and its Scala translation, is NOT the Sieve or Eratosthenes. Instead, it is a much slower algorithm.

The main distinction is that the Sieve crosses all multiples of p for a prime p, even if the number was already crossed, while the Haskell algorithm tests each number against all primes, or up to the first that can divide it.

The performance analysis can be found in the referenced paper.

TimA said...

@Landei, @Daniel Thanks for your comments. I was aware that there was some recent discussion about the validity of the classical functional sieve of eratosthenes algorithm. The putpose of my post was probably just to show the new #:: operator and its (I think) recent ability to be used in pattern matching.