简体   繁体   中英

Code to compute Stream of primes in Scala

I have slightly modified Daniel Sobral's prime Stream function from this SO post :

def primeStream: Stream[Int] => Stream[Int] =
  s => s.head #:: primeStream(s.tail filter(_ % s.head != 0))

I'm using it with:

primeStream(Stream.from(2)).take(100).foreach(println)

and it works fine enough, but I'm wondering if I could get rid of that pesky Stream.from(2) with the following:

def primeStream: def primeStream: () => Stream[Int] = 
  () => Stream.from(2)  

def primeStream: Stream[Int] => Stream[Int] =
  s => s.head #:: primeStream(s.tail filter(_ % s.head != 0))

to achieve:

primeStream().take(100).foreach(println)

But that doesn't work. What am I missing?

I tried also:

def primeStream: Stream[Int] => Stream[Int] = {
  () => Stream.from(2)
  s: Stream[Int] => s.head #:: primeStream(s.tail filter(_ % s.head != 0))
}

which doesn't work.

This works:

def primeStream2(s: Stream[Int] = Stream.from(2)): Stream[Int] =
  s.head #:: primeStream2(s.tail filter(_ % s.head != 0))

But I wanted to understand what I missed to make the syntax work for the more symmetric syntax above with 2 parallel definitions of primeStream .

The 1st attempt doesn't work because you're trying to define 2 different methods with the same name. Methods can't be differentiated by their return types. Also, other than their names they appear to be totally unrelated so if you were able to invoke one of them the existence of the other would be immaterial.

The 2nd attempt tries to put 2 unrelated, and unnamed, functions in the same code block. It will compile if you wrap the 1st function in parentheses but the result isn't what you're after.

I completely understand your desire to make Stream.from(2) automatic because if you pass anything else, like Stream.from(13) , you don't get a Stream of prime integers.

There are a few different ways to get a lazy sequence of prime numbers with only one Stream invocation. This one is a little complicated because it tries to reduce the number of inner iterations when searching for the next prime.

val primeStream: Stream[Int] = 2 #:: Stream.iterate[Int](3)(x =>
  Stream.iterate(x+2)(_+2).find(i => primeStream.takeWhile(p => p*p <= i)
     .forall(i%_ > 0)).get)

You can also use the new (Scala 2.13) unfold() method to create the Stream .

val primes = Stream.unfold(List(2)) { case hd::tl =>
  Option((hd, Range(hd+1, hd*2).find(n => tl.forall(n % _ > 0)).get::hd::tl))
}

Note that Stream has been deprecated since Scala 2.13 and should be replaced with the new LazyList .

There are many different ways to get a Stream of primes. Here's one.

val primeStream: Stream[Int] = 2 #:: Stream.iterate[Int](3)(x =>
  Stream.iterate(x+2)(_+2).find(i => primeStream.takeWhile(p => p*p <= i).forall(i%_ > 0)).get)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM