Slide 1

Slide 1 text

FP The Good, the Bad and the Ugly @DanielaSfregola LSUG - November 2019

Slide 2

Slide 2 text

Hellooooo • Italian living in London UK • Former Java Developer • Scala Lover

Slide 3

Slide 3 text

• Rome, Cinecitta' 
 23 December 1966 • Director
 Sergio Leone • Music
 Ennio Morricone

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

FP: The Good

Slide 6

Slide 6 text

Increased Productivity

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Purity Composability

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

FP: The Bad

Slide 15

Slide 15 text

Learning Curve

Slide 16

Slide 16 text

Functional Programming
 != 
 Categorical Programming

Slide 17

Slide 17 text

You do not need to know Category Theory to write good 
 Functional code

Slide 18

Slide 18 text

...but Monads are EASY!

Slide 19

Slide 19 text

A Monad is just a Monoid in the Category of Endofunctors

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Is Lasagna a Monad?

Slide 22

Slide 22 text

The importance of talks and tutorials for Beginners

Slide 23

Slide 23 text

The Rock Star Developer Syndrome

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

Be a Leader not a "Rock Star"

Slide 26

Slide 26 text

FP: The Ugly

Slide 27

Slide 27 text

Knowing when to break the rules

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Scala FP OOP

Slide 37

Slide 37 text

Scala is Perfect

Slide 38

Slide 38 text

Scala is Perfect not

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Thank You! •Twitter: @DanielaSfregola •Blog: danielasfregola.com •Book: Get Programming with Scala
 by Manning