Laziness: I'll think about a title later
scala> false && { println(" !!" ); true } // does not print anything
res0: Boolean = false
scala> true || { println(" !!" ); false } // doesn't print anything either
res1: Boolean = true
Lazy vs. Strict Equational reasoning
List (1 ,2 ,3 ,4 ) map (_ + 10 ) filter (_ % 2 == 0 ) map (_ * 3 )
List (11 ,12 ,13 ,14 ) filter (_ % 2 == 0 ) map (_ * 3 )
List (12 ,14 ) map (_ * 3 )
List (36 ,42 )
Stream (1 ,2 ,3 ,4 ).map(_ + 10 ).filter(_ % 2 == 0 )
(11 #:: Stream (2 ,3 ,4 ).map(_ + 10 )).filter(_ % 2 == 0 )
Stream (2 ,3 ,4 ).map(_ + 10 ).filter(_ % 2 == 0 )
(12 #:: Stream (3 ,4 ).map(_ + 10 )).filter(_ % 2 == 0 )
12 #:: Stream (3 ,4 ).map(_ + 10 ).filter(_ % 2 == 0 )
12 #:: (13 #:: Stream (4 ).map(_ + 10 )).filter(_ % 2 == 0 )
12 #:: Stream (4 ).map(_ + 10 ).filter(_ % 2 == 0 )
12 #:: (14 #:: Stream ().map(_ + 10 )).filter(_ % 2 == 0 )
12 #:: 14 #:: Stream ().map(_ + 10 ).filter(_ % 2 == 0 )
12 #:: 14 #:: Stream ()
While a recursive function consumes data and eventually terminates, a corecursive function produces data and coterminates.
scala> val ones : Stream [Int ] = 1 #:: ones
ones: Stream [Int ] = Stream (1 , ? )
scala> ones.take(5 ).toList
res11: List [Int ] = List (1 , 1 , 1 , 1 , 1 )
scala> ones.exists(_ % 2 != 0 )
res12: Boolean = true
Laziness lets us separate the description of an expression from the evaluation of that expression.