LAZY EVALUATION
   EM SCALA
LAZY EVALUATION
   EM SCALA
     Pedro Matiello
   pmatiello@gmail.com
       @pmatiello
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
•Aavaliação da expressão é atrasada até que o
valor seja necessário (non-strict evaluation)
• Avaliações   repetidas são evitadas (sharing)
SHORT-CIRCUIT EVALUATION
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 && condicao3
Avaliou condicao1
Avaliou condicao1
Avaliou condicao2
res0: 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 && condicao3
Avaliou condicao1
Avaliou condicao1
Avaliou condicao2
res0: Boolean = false

(não é lazy evaluation)
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)
  }
}
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 }
0
1
2
3
4
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 }
0
1
2 (apenas non-strict evaluation)
3
4
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>
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 y
avaliou x
res0: 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 y
avaliou x
res0: 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 y
avaliou x
res0: java.lang.String = XXX

scala> if (true) x else y
res1: java.lang.String = XXX
STREAMS
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
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
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).toList
res1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
CONTUDO, PORÉM, TODAVIA
•ALazy Evaluation e a Eager Evaluation podem
produzir resultados diferentes
EAGER

1   var y = 2
2   val x = y
3   y = 3
4   println("x = " + x)
EAGER
                             y=2
1   var y = 2
2   val x = y
3   y = 3
4   println("x = " + x)
EAGER
                             y=2, x=2
1   var y = 2
2   val x = y
3   y = 3
4   println("x = " + x)
EAGER
                             y=3, x=2
1   var y = 2
2   val x = y
3   y = 3
4   println("x = " + x)
EAGER
                             y=3, x=2
1   var y = 2
2   val x = y
3   y = 3
4   println("x = " + x)

x = 2
LAZY

1   var y = 2
2   lazy val x = y
3   y = 3
4   println("x = " + x)
LAZY
                             y=2
1   var y = 2
2   lazy val x = y
3   y = 3
4   println("x = " + x)
LAZY
                             y=2, x=y
1   var y = 2
2   lazy val x = y
3   y = 3
4   println("x = " + x)
LAZY
                             y=3, x=y
1   var y = 2
2   lazy val x = y
3   y = 3
4   println("x = " + x)
LAZY
                             y=3, x=3
1   var y = 2
2   lazy val x = y
3   y = 3
4   println("x = " + x)

x = 3
•O sharing do resultado das expressões pode elevar
o consumo de memória
SHARING
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
• Errospodem aparecer em locais diferentes do
 código
EAGER
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)
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)
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 EVALUATION
       EM SCALA
           Pedro Matiello
     pmatiello@gmail.com
              @pmatiello

Lazy Evaluation em Scala

  • 1.
  • 2.
    LAZY EVALUATION EM SCALA Pedro Matiello pmatiello@gmail.com @pmatiello
  • 3.
  • 4.
    • Tipagem estática • Programação orientada a objetos • Programação funcional
  • 5.
  • 6.
    •A operação fundamental é a aplicação de funções
  • 7.
    • Um programa é uma função • Normalmente composta de outras funções •A entrada são os argumentos •A saída é o valor devolvido
  • 8.
  • 9.
    • Transparência referencial (referential transparency) •A aplicação de uma função não produz efeitos colaterais
  • 10.
    • Funções de ordem superior (higher-order functions) • Avaliação atrasada (lazy evaluation)
  • 11.
  • 12.
    •Aavaliação da expressãoé atrasada até que o valor seja necessário (non-strict evaluation)
  • 13.
    • Avaliações repetidas são evitadas (sharing)
  • 14.
    SHORT-CIRCUIT EVALUATION def condicao1= { println("Avaliou condicao1"); true } def condicao2 = { println("Avaliou condicao2"); false } def condicao3 = { println("Avaliou condicao3"); true }
  • 15.
    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
  • 16.
    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 Avaliou condicao1 Avaliou condicao1 Avaliou condicao2 res0: Boolean = false
  • 17.
    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 Avaliou condicao1 Avaliou condicao1 Avaliou condicao2 res0: Boolean = false (não é lazy evaluation)
  • 18.
    CALL BY NAME defloop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) } }
  • 19.
    CALL BY NAME defloop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) } }
  • 20.
    CALL BY NAME defloop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) } } var i = 0; loop(i < 5) { println(i); i=i+1 }
  • 21.
    CALL BY NAME defloop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) } } var i = 0; loop(i < 5) { println(i); i=i+1 } 0 1 2 3 4
  • 22.
    CALL BY NAME defloop(condicao: => Boolean)(expressao: => Unit) { if (condicao) { expressao loop(condicao)(expressao) } } var i = 0; loop(i < 5) { println(i); i=i+1 } 0 1 2 (apenas non-strict evaluation) 3 4
  • 23.
    LAZY VALS scala> lazyval x = { println("avaliou x"); "XXX" } x: java.lang.String = <lazy> scala> lazy val y = { println("avaliou y"); "YYY" } y: java.lang.String = <lazy>
  • 24.
    LAZY VALS scala> lazyval x = { println("avaliou x"); "XXX" } x: java.lang.String = <lazy> scala> lazy val y = { println("avaliou y"); "YYY" } y: java.lang.String = <lazy>
  • 25.
    LAZY VALS scala> lazyval 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
  • 26.
    LAZY VALS scala> lazyval 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 avaliou x res0: java.lang.String = XXX
  • 27.
    LAZY VALS scala> lazyval 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 avaliou x res0: java.lang.String = XXX scala> if (true) x else y
  • 28.
    LAZY VALS scala> lazyval 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 avaliou x res0: java.lang.String = XXX scala> if (true) x else y res1: java.lang.String = XXX
  • 29.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy>
  • 30.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy>
  • 31.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy>
  • 32.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy>
  • 33.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy>
  • 34.
    STREAMS scala> lazy valnaturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy> scala> naturais.take(20)
  • 35.
    STREAMS scala> lazy valnaturais: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) ! ...
  • 36.
    STREAMS scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy>
  • 37.
    STREAMS scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy> scala> naturais.take(20)
  • 38.
    STREAMS scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy> scala> naturais.take(20) res0: scala.collection.immutable.Stream[Int] = Stream(0, ?)
  • 39.
    STREAMS scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy> scala> naturais.take(20).toList res1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
  • 40.
  • 41.
    •ALazy Evaluation ea Eager Evaluation podem produzir resultados diferentes
  • 42.
    EAGER 1 var y = 2 2 val x = y 3 y = 3 4 println("x = " + x)
  • 43.
    EAGER y=2 1 var y = 2 2 val x = y 3 y = 3 4 println("x = " + x)
  • 44.
    EAGER y=2, x=2 1 var y = 2 2 val x = y 3 y = 3 4 println("x = " + x)
  • 45.
    EAGER y=3, x=2 1 var y = 2 2 val x = y 3 y = 3 4 println("x = " + x)
  • 46.
    EAGER y=3, x=2 1 var y = 2 2 val x = y 3 y = 3 4 println("x = " + x) x = 2
  • 47.
    LAZY 1 var y = 2 2 lazy val x = y 3 y = 3 4 println("x = " + x)
  • 48.
    LAZY y=2 1 var y = 2 2 lazy val x = y 3 y = 3 4 println("x = " + x)
  • 49.
    LAZY y=2, x=y 1 var y = 2 2 lazy val x = y 3 y = 3 4 println("x = " + x)
  • 50.
    LAZY y=3, x=y 1 var y = 2 2 lazy val x = y 3 y = 3 4 println("x = " + x)
  • 51.
    LAZY y=3, x=3 1 var y = 2 2 lazy val x = y 3 y = 3 4 println("x = " + x) x = 3
  • 52.
    •O sharing doresultado das expressões pode elevar o consumo de memória
  • 53.
    SHARING scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy>
  • 54.
    SHARING scala> lazy valnaturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int] = <lazy> scala> naturais.foreach{ x:Int => }
  • 55.
    SHARING scala> lazy valnaturais: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
  • 56.
    SHARING scala> lazy valnaturais: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
  • 57.
    • Errospodem aparecerem locais diferentes do código
  • 58.
    EAGER 1 val x = { throw new RuntimeException; 5 } 2 println("x + 3 =") 3 println(x+3)
  • 59.
    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)
  • 60.
    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)
  • 61.
    LAZY 1 lazy val x = { throw new RuntimeException; 5 } 2 println("x + 3 =") 3 println(x+3)
  • 62.
    LAZY 1 lazy val x = { throw new RuntimeException; 5 } 2 println("x + 3 =") 3 println(x+3)
  • 63.
    LAZY 1 lazy val x = { throw new RuntimeException; 5 } 2 println("x + 3 =") 3 println(x+3) x + 3 =
  • 64.
    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)
  • 65.
    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)
  • 66.
    LAZY EVALUATION EM SCALA Pedro Matiello pmatiello@gmail.com @pmatiello