En primer lugar: la lazy
en su segunda línea no está haciendo nada, puede eliminarlo y obtener el mismo resultado.
que es más importante: takeWhile
es en realidad perezoso, ya que sólo devuelve otra Stream
, y nada más allá de la cabeza de esa corriente será evaluado hasta que sea necesario. Considere lo siguiente:
val s = Stream.from(1).takeWhile(_ > 0)
Usted y yo sabemos que s
va a haber un flujo infinito, pero si nos estimulan al REPL y tipo esto en, es perfectamente feliz evaluarlo:
scala> val s = Stream.from(1).takeWhile(_ > 0)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
Lo mismo está sucediendo en su ejemplo: el (Int) ⇒ Boolean
que ha pasado al takeWhile
no va a alimentar ningún elemento más allá de la cabecera de la secuencia, hasta que algo como su foreach
lo haga necesario.
Esto se puede ver aún más drásticamente mediante la adición de algo así como un println
interior de la takeWhile
predicado:
scala> val s = Stream.from(1).takeWhile { x => println("Checking: " + x); x < 4 }
Checking: 1
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> val l = s.toList
Checking: 2
Checking: 3
Checking: 4
l: List[Int] = List(1, 2, 3)
Es evidente que el predicado sólo se obtiene la llamada para la cabeza de la corriente, hasta que forzar la evaluación de la resto de la secuencia llamando al toList
.