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

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

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

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

Avatar for Pishen Tsai

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