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?