answerkey/laziness/01.answer.md
// The natural recursive solution
def toListRecursive: List[A] = this match
case Cons(h,t) => h() :: t().toListRecursive
case Empty => Nil
/*
The above solution will stack overflow for large lazy lists, since it's
not tail-recursive. Here is a tail-recursive implementation. At each
step we cons onto the front of the `acc` list, which will result in the
reverse of the lazy list. Then at the end we reverse the result to get the
correct order again.
*/
def toList: List[A] =
@annotation.tailrec
def go(ll: LazyList[A], acc: List[A]): List[A] = ll match
case Cons(h, t) => go(t(), h() :: acc)
case Empty => acc.reverse
go(this, Nil)
/*
In order to avoid the `reverse` at the end, we could write it using a
mutable list buffer and an explicit loop instead. Note that the mutable
list buffer never escapes our `toList` method, so this function is
still _pure_.
*/
def toListFast: List[A] =
val buf = new collection.mutable.ListBuffer[A]
@annotation.tailrec
def go(ll: LazyList[A]): List[A] = ll match
case Cons(h, t) =>
buf += h()
go(t())
case Empty => buf.toList
go(this)