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

ScalaBase 2021- FP: the Good, the Bad, the Ugly

ScalaBase 2021- FP: the Good, the Bad, 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.

Daniela Sfregola

May 14, 2021
Tweet

More Decks by Daniela Sfregola

Other Decks in Programming

Transcript

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

    Scalabase 2021

    View full-size slide

  2. Hellooooo
    • Software Engineer 

    living in London UK

    • Former Java Developer

    • Scala Lover ❤

    • OS Maintainer

    • Author of 

    "Get Programming with Scala"
    by Manning


    35% OFF with code "ctwscalabase21"

    View full-size slide

  3. • Rome, Cinecitta' 

    23 December 1966

    • Director

    Sergio Leone

    • Music

    Ennio Morricone

    View full-size slide

  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

    View full-size slide

  5. FP: The Good

    View full-size slide

  6. Increased
    Productivity

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  10. RTness
    Totality
    Purity
    +
    =

    View full-size slide

  11. Referential Transparent
    same input same output

    Totality
    always return a value

    View full-size slide

  12. Is this Pure?
    import java.time.ZonedDateTime
    def plusDays(n: Int): ZonedDateTime =
    ZonedDateTime.now().plusDays(n)
    - Referentially Transparent?
    - Total?

    View full-size slide

  13. Is this Pure?
    import java.time.ZonedDateTime
    def plusDays(n: Int): ZonedDateTime =
    ZonedDateTime.now().plusDays(n)
    - Referentially Transparent? ⛔
    - Total? ✅

    View full-size slide

  14. Is this Pure?
    def div(a: Int, b: Int): Int = a / b
    - Referentially Transparent?
    - Total?

    View full-size slide

  15. Is this Pure?
    def div(a: Int, b: Int): Int = a / b
    - Referentially Transparent? ✅
    - Total? ⛔

    View full-size slide

  16. Is this Pure?
    def sum(a: Int, b: Int): Int = a + b
    - Referentially Transparent?
    - Total?

    View full-size slide

  17. Is this Pure?
    def sum(a: Int, b: Int): Int = a + b
    - Referentially Transparent? ✅
    - Total? ✅

    View full-size slide

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

    View full-size slide

  19. Purity
    def foo(s: String): Unit = {
    // implementation here
    }
    Impure
    def foo(s: String): Int = {
    // implementation here
    }
    Pure

    View full-size slide

  20. Purity
    Composability

    View full-size slide

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

    View full-size slide

  22. Learning Curve

    View full-size slide

  23. Functional
    Programming

    != 

    Categorical
    Programming

    View full-size slide

  24. You do not need to know
    Category Theory
    to write good 

    Functional code

    View full-size slide

  25. ...but Monads are
    EASY!

    View full-size slide

  26. A Monad is just
    a Monoid
    in the Category of
    Endofunctors

    View full-size slide

  27. Monads are like

    Burritos
    from https://twitter.com/monadburritos/status/915624691829587968

    View full-size slide

  28. Is Lasagna a Monad?

    View full-size slide

  29. The importance of
    talks and tutorials
    for Beginners

    View full-size slide

  30. The Rock Star
    Developer Syndrome

    View full-size slide

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

    View full-size slide

  32. Be a Leader
    not a "Rock Star"

    View full-size slide

  33. FP: The Ugly

    View full-size slide

  34. Knowing when to
    break the rules

    View full-size slide

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

    View full-size slide

  36. 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

    View full-size slide

  37. 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

    View full-size slide

  38. 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
    toArrayOOP avg execution: 0.002 ms
    toArrayFP avg execution: 0.028 ms

    View full-size slide

  39. JVM and FP
    do not always go along...
    OOP version
    is much faster than the
    FP one!

    View full-size slide

  40. 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)
    }

    View full-size slide

  41. 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

    View full-size slide

  42. If you have a really good reason,
    break the rules!
    ...but keep the ugly bits isolated

    View full-size slide

  43. Thank You!
    •Twitter: @DanielaSfregola

    •"Get Programming with Scala" 

    by Manning


    35% OFF with code "ctwscalabase21"

    View full-size slide