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

都什麼時代了,你還在寫 while loop 嗎?

都什麼時代了,你還在寫 while loop 嗎?

Pishen Tsai

October 19, 2018
Tweet

More Decks by Pishen Tsai

Other Decks in Programming

Transcript

  1. ){}w ile(){}w {}while(){}w le(){}while(){}w }while(){}while(){}w e(){}while(){}while(){}w while(){}while(){}while(){}w (){}while(){}while(){}while(){}w hile(){}while(){}while(){}while(){}w ){}while(){}while(){}while(){}while(){}w

    ile(){}while(){}while(){}while(){}while(){}w {}while(){}while(){}while(){}while(){}while(){}w 都什麼時代了 你還在寫 while loop 嗎? INFECTED PROGRAM WHILE LOOP @pishen
  2. Pishen Vpon 5 years Scala Scala Taiwan Open Source VocaRadio

    sbt-lighter annoy4s AkkaUI Gitter Facebook Scala Kitchen 日本 Scala 旅遊團 https://gitter.im/ScalaTaiwan/ScalaTaiwan https://www.facebook.com/groups/ScalaTW/ https://www.meetup.com/Scala-Taiwan-Meetup/ Meetup (each month) Since 2015 冬
  3. var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates

    :+ dates.last.plusDays(1) } println(dates) java.time.LocalDate
  4. var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates

    :+ dates.last.plusDays(1) } println(dates) append List(1,2,3) :+ 4 List(1,2,3,4)
  5. var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates

    :+ dates.last.plusDays(1) } println(dates) dates.length == x dates.length == x + 1
  6. var dates = List(startDate) //while (dates.last.isBefore(endDate)) { // // //

    dates = dates :+ dates.last.plusDays(1) // // //} println(dates) ✔ Compiler still pass! dates.length == x dates.length == x + 1
  7. var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates

    :+ dates.last.plusDays(1) } println(dates) dates.length == x dates.length == x + 1
  8. var dates = List(startDate) println(dates) while (dates.last.isBefore(endDate)) { dates =

    dates :+ dates.last.plusDays(1) } dates.length == x dates.length == x + 1 ✔ Compiler still pass!
  9. var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates

    :+ dates.last.plusDays(1) } println(dates) dates.length == x dates.length == x + 1 An optional part of code that *will* change the program's behavior. ?
  10. 1970s Don't use GOTO 1995 25 years GOTO is prohibited!

    https://en.wikipedia.org/wiki/Goto 2018 23 years Don't use while
  11. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  12. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  13. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  14. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) return You don't have to write "return" in Scala's function.
  15. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) iterate [d1,d2,d3,d4,d5] iterate [d1] iterate [d1,d2] iterate [d1,d2,d3] iterate [d1,d2,d3,d4] [d1,d2,d3,d4,d5] [d1,d2,d3,d4,d5] [d1,d2,d3,d4,d5] [d1,d2,d3,d4,d5] [d1,d2,d3,d4,d5]
  16. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  17. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  18. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) dates.length == x
  19. //def iterate(dates: List[LocalDate]): List[LocalDate] = { // if (dates.last.isBefore(endDate)) {

    // iterate(dates :+ dates.last.plusDays(1)) // } else { // dates // } //} val dates = iterate(List(startDate)) println(dates) ✗ Compile Error!
  20. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates)
  21. val dates = iterate(List(startDate)) def iterate(dates: List[LocalDate]): List[LocalDate] = {

    if (dates.last.isBefore(endDate)) { iterate(dates :+ dates.last.plusDays(1)) } else { dates } } println(dates) ✗ Compile Error!
  22. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) An explicit part of code for easier code tracing.
  23. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates :+ dates.last.plusDays(1) } println(dates)
  24. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates :+ dates.last.plusDays(1) } println(dates)
  25. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } val dates = iterate(List(startDate)) println(dates) var dates = List(startDate) while (dates.last.isBefore(endDate)) { dates = dates :+ dates.last.plusDays(1) } println(dates)
  26. def iterate(dates: List[LocalDate]): List[LocalDate] = { if (dates.last.isBefore(endDate)) { iterate(dates

    :+ dates.last.plusDays(1)) } else { dates } } Tail Recursion Only call yourself at the last position. Tail Call Optimization Prevent memory from stack overflow. https://en.wikipedia.org/wiki/Tail_call https://www.artima.com/pins1ed/functions-and-closures.html#8.9 Not available in Java ⚠
  27. 1 2 3 4 5 6 7 val numbers =

    Stream.range(1, 8) Not evaluated (Take no memory)
  28. 1 2 3 4 5 6 7 Not evaluated (Take

    no memory) val numbers = Stream.range(1, 8) val n2 = numbers(2)
  29. 1 2 3 4 5 6 7 val numbers =

    Stream.range(1, 8) val n2 = numbers(2) Memoization
  30. 1 2 3 4 5 6 7 val numbers =

    Stream.range(1, 8) val n2 = numbers(2) val n4 = numbers(4) Memoization
  31. 1 2 3 4 5 6 7 Memoization val numbers

    = Stream.range(1, 8) val n2 = numbers(2) val n4 = numbers(4)
  32. 1 2 3 4 5 6 7 val numbers =

    Stream.range(1, 8) val n2 = numbers(2) val n4 = numbers(4) val list = numbers.toList
  33. val numbers = Stream.range(1, 8) val n2 = numbers(2) val

    n4 = numbers(4) val list = numbers.toList 1 2 3 4 5 6 7 1 2 3 4 5 6 7 list
  34. Stream.continually(1) Stream.iterate(0)(x => x + 2) 1 1 1 1

    1 1 1 1 1 1 1 1 1 1 1 0 2 4 6 8 10 12 14 16 18 20 2 +2 +2 +2 Stream.continually(List(1,2,3)).flatten 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 lambda function
  35. stream.map(x => x * 2) 1 2 3 4 5

    6 7 8 9 10 11 1 2 4 6 8 10 12 14 16 18 20 22 2
  36. stream.filter(x => x % 2 == 1) 1 2 3

    4 5 6 7 8 9 10 11 1 1 3 5 7 9 11 13 15 17 19 21 2
  37. stream.flatMap(x => List(x, x)) 1 2 3 4 5 6

    7 8 9 10 11 1 1 1 2 2 3 3 4 4 5 5 6 1 1 2 2 3 3 4 4 5 5 6 6
  38. stream.takeWhile(x => x < 6) 1 2 3 4 5

    6 7 8 9 10 11 1 1 2 3 4 5
  39. val numbers = Stream.iterate(0)(_ + 1) val n3 = numbers(3)

    1 2 3 4 5 6 7 8 9 10 11 1 val numbers = Iterator.iterate(0)(_ + 1) val n3 = numbers(3) 1 2 3 4 5 6 7 8 9 10 11 1 Works like Java's Stream Memoization
  40. 1 2 3 4 5 6 7 Stream.range(1, 8) LazyList.range(1,

    8) 1 2 3 4 5 6 7 Scala 2.13.0 (fully lazy)
  41. val page: Page = getFirstPage() val items: List[Item] = page.getItems()

    val hasNext: Boolean = page.hasNextPage() val nextPage: Page = page.getNextPage() May return null if Page doesn't exist. Given a number n, please return first n items to me?
  42. def take(n: Int): List[Item] = { var page = getFirstPage()

    if (page != null) { var items = page.getItems() while(page.hasNextPage() && items.size < n) { page = page.getNextPage() items = items ++ page.getItems() } items.take(n) } else { List.empty[Item] } }
  43. val items = Stream .iterate(getFirstPage())(_.getNextPage) .takeWhile(_ != null) .flatMap(_.getItems) p1

    p2 p3 null getNextPage() Exceptions p1 p2 p3 takeWhile() i1 i2 i3 i4 i5 i6 i7 i8 i9 flatMap() items.take(5)
  44. val items = Stream .iterate(getFirstPage())(_.getNextPage) .takeWhile(_ != null) .flatMap(_.getItems) p1

    p2 p3 null getNextPage() Exceptions p1 p2 p3 takeWhile() i1 i2 i3 i4 i5 i6 i7 i8 i9 flatMap() items.take(5) items.take(8)
  45. val items = Stream .iterate(getFirstPage())(_.getNextPage) .takeWhile(_ != null) .flatMap(_.getItems) p1

    p2 p3 null getNextPage() Exceptions p1 p2 p3 takeWhile() i1 i2 i3 i4 i5 i6 i7 i8 i9 flatMap() items.take(5) items.take(8)
  46. stream.tail 1 2 3 4 5 6 7 8 9

    10 11 1 2 3 4 5 6 7 8 9 10 11 1
  47. streamA.zip(streamB) 1 2 3 4 5 6 7 8 9

    10 11 streamA 1 2 3 1 2 3 1 2 3 1 2 streamB
  48. streamA.zip(streamB).map { case (a, b) => a + b }

    1 2 3 4 5 6 7 8 9 10 11 streamA 1 2 3 1 2 3 1 2 3 1 2 streamB 2 4 6 5 7 9 8 10 12 11 13
  49. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 fibs 0 1 fibs 1 fibs.tail
  50. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 0 1 1 fibs fibs fibs.tail
  51. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 0 1 1 1 1 fibs fibs fibs.tail
  52. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 2 0 1 1 1 1 fibs fibs fibs.tail
  53. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 2 0 1 1 2 1 1 2 fibs fibs fibs.tail
  54. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 2 3 0 1 1 2 1 1 2 fibs fibs fibs.tail
  55. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 2 3 0 1 1 2 3 1 1 2 3 fibs fibs fibs.tail
  56. val fibs: Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map {

    case (a, b) => a + b } 0 1 1 2 3 5 8 13 21 34 55 0 1 1 2 3 5 8 13 21 1 1 2 3 5 8 13 21 34 fibs fibs fibs.tail