Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lazy Evaluation em Scala

Lazy Evaluation em Scala

Presented at: TDC 2012, July/2012.

E54f4140dc133a17200fe7a104c33a8e?s=128

Pedro Matiello

July 07, 2012
Tweet

Transcript

  1. LAZY EVALUATION EM SCALA

  2. Pedro Matiello pmatiello@gmail.com @pmatiello LAZY EVALUATION EM SCALA

  3. SCALA

  4. •Tipagem estática •Programação orientada a objetos •Programação funcional

  5. PROGRAMAÇÃO FUNCIONAL

  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.          

      f(x) = x²
  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. LAZY EVALUATION

  12. •A avaliação da expressão é atrasada até que o valor

    seja necessário (non-strict evaluation)
  13. •Avaliações repetidas são evitadas (sharing)

  14. def condicao1 = { println("Avaliou condicao1"); true } def condicao2

    = { println("Avaliou condicao2"); false } def condicao3 = { println("Avaliou condicao3"); true } SHORT-CIRCUIT EVALUATION
  15. 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
  16. 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
  17. 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 (não é lazy evaluation)
  18. def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) {

    expressao loop(condicao)(expressao) } } CALL BY NAME
  19. def loop(condicao: => Boolean)(expressao: => Unit) { if (condicao) {

    expressao loop(condicao)(expressao) } } CALL BY NAME
  20. 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
  21. 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
  22. 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 (apenas non-strict evaluation)
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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
  28. 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 LAZY VALS
  29. scala> lazy val naturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int]

    = <lazy> STREAMS
  30. scala> lazy val naturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int]

    = <lazy> STREAMS  QDWXUDLVPDS B QDWXUDLV
  31.  QDWXUDLV   scala> lazy val naturais:List[Int] = 0

    :: naturais.map(_+1) naturais: List[Int] = <lazy> STREAMS
  32.  QDWXUDLV    scala> lazy val naturais:List[Int] =

    0 :: naturais.map(_+1) naturais: List[Int] = <lazy> STREAMS
  33.  QDWXUDLV     scala> lazy val naturais:List[Int]

    = 0 :: naturais.map(_+1) naturais: List[Int] = <lazy> STREAMS
  34. scala> lazy val naturais:List[Int] = 0 :: naturais.map(_+1) naturais: List[Int]

    = <lazy> scala> naturais.take(20) STREAMS
  35. 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
  36. scala> lazy val naturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int]

    = <lazy> STREAMS
  37. scala> lazy val naturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int]

    = <lazy> scala> naturais.take(20) STREAMS
  38. 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
  39. 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) STREAMS
  40. CONTUDO, PORÉM, TODAVIA

  41. •A Lazy Evaluation e a Eager Evaluation podem produzir resultados

    diferentes
  42. 1 var y = 2 2 val x = y

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

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

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

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

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

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

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

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

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

    y 3 y = 3 4 println("x = " + x) x = 3 y=3, x=3 LAZY
  52. •O sharing do resultado das expressões pode elevar o consumo

    de memória
  53. scala> lazy val naturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int]

    = <lazy> SHARING
  54. scala> lazy val naturais:Stream[Int] = 0 #:: naturais.map(_+1) naturais: Stream[Int]

    = <lazy> scala> naturais.foreach{ x:Int => } SHARING
  55. 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
  56. 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
  57. •Erros podem aparecer em locais diferentes do código

  58. 1 val x = { throw new RuntimeException; 5 }

    2 println("x + 3 =") 3 println(x+3) EAGER
  59. 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
  60. 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
  61. 1 lazy val x = { throw new RuntimeException; 5

    } 2 println("x + 3 =") 3 println(x+3) LAZY
  62. 1 lazy val x = { throw new RuntimeException; 5

    } 2 println("x + 3 =") 3 println(x+3) LAZY
  63. 1 lazy val x = { throw new RuntimeException; 5

    } 2 println("x + 3 =") 3 println(x+3) x + 3 = LAZY
  64. 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
  65. 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
  66. LAZY EVALUATION EM SCALA Pedro Matiello pmatiello@gmail.com @pmatiello