I'm trying to implement an infinite stream with a filter operation. I want to make it not crash with a stack overflow error by using lazy evaluation for the tail.
abstract class MyStream[+A] {
def head: A
def tail: MyStream[A]
def #::[B >: A](element: B): MyStream[B] // prepend operator
def filter(predicate: A => Boolean): MyStream[A]
}
class FiniteStream[+A](val head: A, val tail: MyStream[A]) extends MyStream[A] {
override def #::[B >: A](element: B): MyStream[B] = new FiniteStream[B](element, this)
override def filter(predicate: A => Boolean): MyStream[A] = {
lazy val filteredTail = tail.filter(predicate)
if (predicate(head)) filteredTail
else filteredTail
}
}
class InfiniteStream[+A](override val head: A, generator: A => A) extends MyStream[A] {
override def tail: MyStream[A] = {
lazy val tail = new InfiniteStream[A](generator(head), generator)
tail
}
override def #::[B >: A](element: B): MyStream[B] =
new FiniteStream[B](element, this)
override def filter(predicate: A => Boolean): MyStream[A] = {
lazy val filteredTail = tail.filter(predicate)
if (predicate(head)) head #:: filteredTail
else filteredTail
}
}
object MyStream {
def from[A](start: A)(generator: A => A): MyStream[A] = new InfiniteStream[A](start, generator)
}
val stream: MyStream[Int] = MyStream.from(1)((n: Int) => n + 1)
val filtered = stream.filter(_ % 2 == 0)
But this program does indeed crash with a stack overflow error. It seems like my lazy evaluation strategy does not work. The tail is still being evaluated. Why?
FiniteStream? Where/what is that? - jwvh