LAZY EVALUATIONEM SCALA
SCALA
•Tipagem estática
•Programação orientada a objetos
•Programação funcional
PROGRAMAÇÃO FUNCIONAL
•A operação fundamental é a aplicação de funções
•Um programa é uma função
•Normalmente composta de outras funções
•A entrada são os argumentos
•A saída é o valor devolvido
�
�
�
�
�
�
�
�
�
��
��
��
f(x) = x²
•Transparência referencial (referential transparency)
•A aplicação de uma função não produz efeitos colaterais
•Funções de ordem superior (higher-order functions)
•Avaliação atrasada (lazy evaluation)
LAZY EVALUATION
•A avaliação da expressão é atrasada até que o valor seja necessário (non-strict evaluation)
•Avaliações repetidas são evitadas (sharing)
def condicao1 = { println("Avaliou condicao1"); true }def condicao2 = { println("Avaliou condicao2"); false }def condicao3 = { println("Avaliou condicao3"); true }
SHORT-CIRCUIT EVALUATION
def condicao1 = { println("Avaliou condicao1"); true }def condicao2 = { println("Avaliou condicao2"); false }def condicao3 = { println("Avaliou condicao3"); true }
scala> condicao1 && condicao1 && condicao2 && condicao3
SHORT-CIRCUIT EVALUATION
def condicao1 = { println("Avaliou condicao1"); true }def condicao2 = { println("Avaliou condicao2"); false }def condicao3 = { println("Avaliou condicao3"); true }
scala> condicao1 && condicao1 && condicao2 && condicao3Avaliou condicao1Avaliou condicao1Avaliou condicao2res0: Boolean = false
SHORT-CIRCUIT EVALUATION
def condicao1 = { println("Avaliou condicao1"); true }def condicao2 = { println("Avaliou condicao2"); false }def condicao3 = { println("Avaliou condicao3"); true }
scala> condicao1 && condicao1 && condicao2 && condicao3Avaliou condicao1Avaliou condicao1Avaliou condicao2res0: Boolean = false
SHORT-CIRCUIT EVALUATION
(não é lazy evaluation)
def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) }}
CALL BY NAME
def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) }}
CALL BY NAME
def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) }}
var i = 0;loop(i < 5) { println(i); i=i+1 }
CALL BY NAME
def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) }}
var i = 0;loop(i < 5) { println(i); i=i+1 }01234
CALL BY NAME
def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) }}
var i = 0;loop(i < 5) { println(i); i=i+1 }01234
CALL BY NAME
(apenas non-strict evaluation)
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
LAZY VALS
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
LAZY VALS
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
scala> if (true) x else y
LAZY VALS
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
scala> if (true) x else yavaliou xres0: java.lang.String = XXX
LAZY VALS
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
scala> if (true) x else yavaliou xres0: java.lang.String = XXX
scala> if (true) x else y
LAZY VALS
scala> lazy val x = { println("avaliou x"); "XXX" }x: java.lang.String = <lazy>
scala> lazy val y = { println("avaliou y"); "YYY" }y: java.lang.String = <lazy>
scala> if (true) x else yavaliou xres0: java.lang.String = XXX
scala> if (true) x else yres1: java.lang.String = XXX
LAZY VALS
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
STREAMS
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
STREAMS
� QDWXUDLV�PDS�B���
QDWXUDLV�
�
QDWXUDLV�
����
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
STREAMS
�
QDWXUDLV�
���� �
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
STREAMS
�
QDWXUDLV�
���� � �
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
STREAMS
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
scala> naturais.take(20)
STREAMS
scala> lazy val naturais:List[Int] =0 :: naturais.map(_+1)
naturais: List[Int] = <lazy>
scala> naturais.take(20)java.lang.StackOverflowError! at .naturais(<console>:7)! at .naturais(<console>:7)! ...
STREAMS
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
STREAMS
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.take(20)
STREAMS
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.take(20)res0: scala.collection.immutable.Stream[Int] = Stream(0, ?)
STREAMS
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.take(20).toListres1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
STREAMS
CONTUDO, PORÉM, TODAVIA
•A Lazy Evaluation e a Eager Evaluation podem produzir resultados diferentes
1 var y = 22 val x = y3 y = 34 println("x = " + x)
EAGER
1 var y = 22 val x = y3 y = 34 println("x = " + x)
y=2
EAGER
1 var y = 22 val x = y3 y = 34 println("x = " + x)
y=2, x=2
EAGER
1 var y = 22 val x = y3 y = 34 println("x = " + x)
y=3, x=2
EAGER
1 var y = 22 val x = y3 y = 34 println("x = " + x)
x = 2
y=3, x=2
EAGER
1 var y = 22 lazy val x = y3 y = 34 println("x = " + x)
LAZY
1 var y = 22 lazy val x = y3 y = 34 println("x = " + x)
y=2
LAZY
1 var y = 22 lazy val x = y3 y = 34 println("x = " + x)
y=2, x=y
LAZY
1 var y = 22 lazy val x = y3 y = 34 println("x = " + x)
y=3, x=y
LAZY
1 var y = 22 lazy val x = y3 y = 34 println("x = " + x)
x = 3
y=3, x=3
LAZY
•O sharing do resultado das expressões pode elevar o consumo de memória
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
SHARING
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.foreach{ x:Int => }
SHARING
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.foreach{ x:Int => }Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
SHARING
scala> lazy val naturais:Stream[Int] =0 #:: naturais.map(_+1)
naturais: Stream[Int] = <lazy>
scala> naturais.foreach{ x:Int => }Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
SHARING
•Erros podem aparecer em locais diferentes do código
1 val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
EAGER
1 val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
Exception in thread "main" java.lang.RuntimeException! at Test$.main(Test.scala:1)! at Test.main(Test.scala)
EAGER
1 val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
Exception in thread "main" java.lang.RuntimeException! at Test$.main(Test.scala:1)! at Test.main(Test.scala)
EAGER
1 lazy val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
LAZY
1 lazy val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
LAZY
1 lazy val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
x + 3 =
LAZY
1 lazy val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
x + 3 =Exception in thread "main" java.lang.RuntimeException! at Test$.main(Test.scala:1)! at Test$.main(Test.scala:3)! at Test.main(Test.scala)
LAZY
1 lazy val x = { throw new RuntimeException; 5 }2 println("x + 3 =")3 println(x+3)
x + 3 =Exception in thread "main" java.lang.RuntimeException! at Test$.main(Test.scala:1)! at Test$.main(Test.scala:3)! at Test.main(Test.scala)
LAZY