views:

95

answers:

2

In Scala, does calling isEmtpy method on an instance of Stream class cause the stream to be evaluated completely? My code is like this:

import Stream.cons

private val odds: Stream[Int] = cons(3, odds.map(_ + 2))
private val primes: Stream[Int] = cons(2, odds filter isPrime)

private def isPrime(n: Int): Boolean = n match {
  case 1 => false
  case 2 => true
  case 3 => true
  case 5 => true
  case 7 => true
  case x if n % 3 == 0 => false
  case x if n % 5 == 0 => false
  case x if n % 7 == 0 => false
  case x if (x + 1) % 6 == 0 || (x - 1) % 6 == 0 => true
  case x => primeDivisors(x) isEmpty
}


import Math.{sqrt, ceil}
private def primeDivisors(n: Int) =
  primes takeWhile { _ <= ceil(sqrt(n))} filter {n % _ == 0 }

So, does the call to isEmpty on the line case x => primeDivisors(x) isEmpty cause all the prime divisors to be evaluated or only the first one?

+7  A: 

Only if the stream is actually empty :)

Otherwise, it will just see if the stream has a head and tail (matches Stream.cons) and return false.

Apocalisp
This is true. `Stream.cons(print("Hello"), Stream(print(" World!"))).isEmpty` will only print out `Hello` and not `Hello World!`. So, only the first element will be evaluated.
Michel Krämer
+2  A: 

Looking at the source:

https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src///library/scala/collection/immutable/Stream.scala#L550

would suggest that once you have a Stream.Cons instance it cannot be empty, so always returns false. It therefore seems likely that the Stream.cons factory method is the one that evaluates the first element, which you can show by running just:

Stream.cons(print("Hello"), Stream(print(" World!")))

in the interpreter and seeing this also prints "Hello".

pdbartlett