LSUG 2019 - FP: The Good, The Bad and The Ugly

LSUG 2019 - FP: The Good, The Bad and The Ugly

You are about to fall in love with Functional Programming, if not already. You are going to learn the good parts that are going to make your day-to-day life easier. But since nobody is perfect - not even FP -, you are also going to see its bad and ugly parts, and you'll discover how to deal with them: from learning challenges to performance issues on the JVM.

E99b07644586e9e1723757bf8e34ea68?s=128

Daniela Sfregola

November 21, 2019
Tweet

Transcript

  1. FP The Good, the Bad and the Ugly @DanielaSfregola LSUG

    - November 2019
  2. Hellooooo • Italian living in London UK • Former Java

    Developer • Scala Lover
  3. • Rome, Cinecitta' 
 23 December 1966 • Director
 Sergio

    Leone • Music
 Ennio Morricone
  4. Everything in Life • Good Parts
 the bits that we

    like • Bad Parts
 the traps to avoid • Ugly Parts
 the parts that we need to live with
  5. FP: The Good

  6. Increased Productivity

  7. Immutability private var i: Int = 0 while (i <

    10) { // do stuff here i = i + 1 } OOP
  8. Immutability private var i: Int = 0 while (i <

    10) { // do stuff here i = i + 1 } OOP (0 until 10).foreach { i => // do stuff here } FP
  9. Immutability private var i: Int = 0 while (i <

    10) { i = i * 2 println(i) i = i + 1 } OOP (0 until 10).foreach { i => println(i * 2) } FP
  10. Purity def length(s: String): Unit = { // implementation here

    } Impure
  11. Purity def length(s: String): Unit = { // implementation here

    } Impure def length(s: String): Int = { // implementation here } Pure
  12. Purity Composability

  13. Puzzle Coding! from https://scalameta.org/metals/ Metals

  14. FP: The Bad

  15. Learning Curve

  16. Functional Programming
 != 
 Categorical Programming

  17. You do not need to know Category Theory to write

    good 
 Functional code
  18. ...but Monads are EASY!

  19. A Monad is just a Monoid in the Category of

    Endofunctors
  20. Monads are like
 Burritos from https://twitter.com/monadburritos/status/915624691829587968

  21. Is Lasagna a Monad?

  22. The importance of talks and tutorials for Beginners

  23. The Rock Star Developer Syndrome

  24. The Rock Star Developer from https://twitter.com/honeypotio/status/689811823281991681

  25. Be a Leader not a "Rock Star"

  26. FP: The Ugly

  27. Knowing when to break the rules

  28. Case Class to Array def toArray(product: Product): Array[Any] = {

    product // Product .productIterator // Iterator[Any] .toArray // Array[Any] } FP
  29. Case Class to Array def toArray(product: Product): Array[Any] = {

    product // Product .productIterator // Iterator[Any] .toArray // Array[Any] } def toArray(product: Product): Array[Any] = { val size = product.productArity val arr = new Array[Any](size) var i = 0 while (i < size) { arr(i) = product.productElement(i) i = i + 1 } arr } FP OOP
  30. Benchmarking* import com.danielasfregola.randomdatagenerator.RandomDataGenerator._ def avgRunTime[A](f: => A, n: Int =

    1000): Double = { val start = Instant.now.toEpochMilli (0 until n).foreach(_ => f) val end = Instant.now.toEpochMilli val diff = end - start diff / n.toDouble } case class BigExample(f1: String, f2: Int, f3: Long, f4: Char, f5: String, f6: String, f7: Int, f8: Long, f9: Char, f10: String, f11: String, f12: Int, f13: Long, f14: Char, f15: String, f16: String, f17: Int, f18: Long, f19: Char, f20: String, f21: String, f22: Int, f23: Long, f24: Char, f25: String, f26: String, f27: Int, f28: Long, f29: Char, f30: String) val big = random[BigExample] avgRunTime(toArrayFP(big)) avgRunTime(toArrayOOP(big)) *not a serious benchmarking, executed on my laptop
  31. Benchmarking* import com.danielasfregola.randomdatagenerator.RandomDataGenerator._ def avgRunTime[A](f: => A, n: Int =

    1000): Double = { val start = Instant.now.toEpochMilli (0 until n).foreach(_ => f) val end = Instant.now.toEpochMilli val diff = end - start diff / n.toDouble } case class BigExample(f1: String, f2: Int, f3: Long, f4: Char, f5: String, f6: String, f7: Int, f8: Long, f9: Char, f10: String, f11: String, f12: Int, f13: Long, f14: Char, f15: String, f16: String, f17: Int, f18: Long, f19: Char, f20: String, f21: String, f22: Int, f23: Long, f24: Char, f25: String, f26: String, f27: Int, f28: Long, f29: Char, f30: String) val big = random[BigExample] avgRunTime(toArrayFP(big)) avgRunTime(toArrayOOP(big)) *not a serious benchmarking, executed on my laptop toArrayFP avg execution: 0.028 ms toArrayOOP avg execution: 0.002 ms
  32. JVM and FP do not always go along... OOP version

    is much faster than the FP one!
  33. My ideal implementation of map function for List[A] final override

    def map[B](f: A => B): List[B] = { @tailrec def loop(l: List[A], res: List[B]): List[B] = { l match { case head :: tail => loop(tail, res :+ f(head)) case Nil => res } } loop(this, res = Nil) }
  34. The real implementation of map function for List[A]* final override

    def map[B](f: A => B): List[B] = { if (this eq Nil) Nil else { val h = new ::[B](f(head), Nil) var t: ::[B] = h var rest = tail while (rest ne Nil) { val nx = new ::(f(rest.head), Nil) t.next = nx t = nx rest = rest.tail } releaseFence() h } } *scala 2.13.0
  35. If you have a really good reason, break the rules!

    ...but keep the ugly bits isolated
  36. Scala FP OOP

  37. Scala is Perfect

  38. Scala is Perfect not

  39. Not even Scala is perfect... • Slow Compiler • pipelining

    compilation by Jason Zaugg • zinc by Eugene Yokota • Tooling • bloop by Jorge Vicente Cantero • metals by Ólafur Páll Geirsson
  40. Thank You! •Twitter: @DanielaSfregola •Blog: danielasfregola.com •Book: Get Programming with

    Scala
 by Manning