Slide 1

Slide 1 text

Saúl Díaz FP FOR OOP DEVS EVENTBRITE

Slide 2

Slide 2 text

Given a list, I want to sum all numbers of it, and return it ?

Slide 3

Slide 3 text

3 fun sumAll(numbers: List) : Int { var result = 0 for(number in numbers) { result += number } return result }

Slide 4

Slide 4 text

Now imagine I don’t know loops exist ?

Slide 5

Slide 5 text

5 fun sumAll(numbers: List) : Int { return when(numbers.size) { 1 -> numbers[0] 2 -> numbers[0] + numbers[1] 3 -> numbers[0] + numbers[1] + numbers[2] /* ... */ } }

Slide 6

Slide 6 text

6 tailrec fun sumAll(numbers: List, sum: Int = 0) : Int { return if (numbers.isEmpty()) { sum } else { sumAll( numbers.subList(0, numbers.lastIndex), sum + numbers.first() ) } }

Slide 7

Slide 7 text

Y U DON’T FP?

Slide 9

Slide 9 text

9 fun sumAll(numbers: List) = numbers.fold(0) { number, sum -> number + sum }

Slide 10

Slide 10 text

10 // With FP only fun sumAll(numbers: List) = numbers.fold(0) { number, sum -> number + sum } val result = sumAll(listOf(1, 2, 3)) // Adding OOP fun List.sum() = fold(0) { number, sum -> number + sum } val result = listOf(1, 2, 3).sum()

Slide 11

Slide 11 text

Y U DON’T FP?

Slide 12

Slide 12 text

fun printAllAttendees (conference: Conference): List { val attendees = HashSet() for (talk in conference.talks) { for (attendee in talk.attendees) { attendees += attendee } } val names = ArrayList() for (attendee in attendees) { names.add("${attendee.id} - ${attendee.name}") } return names } OOP is more readable

Slide 13

Slide 13 text

fun printAllAttendees (conference: Conference): List { val attendees = HashSet() for (talk in conference.talks) { for (attendee in talk.attendees) { attendees += attendee } } val names = ArrayList() for (attendee in attendees) { names.add("${attendee.id} - ${attendee.name}") } return names } OOP is more readable familiar

Slide 14

Slide 14 text

Käännöspalvelu ei ole käytettävissä The brown dog jumpes over the lazy frog OOP is more readable familiar

Slide 15

Slide 15 text

This can also be familiar, too fun printParticipants(conference: Conference): List { return conference.talks .map { talk -> talk.attendees } .flatten() .toSet() .map { attendee -> "${attendee.id} - ${attendee.name}" } }

Slide 16

Slide 16 text

100% of the bugs are caused by source code Reducing LoCs also reduces review times and points of failure

Slide 17

Slide 17 text

17 As developers, we can only give solutions as good as the tools we have at our disposal

Slide 18

Slide 18 text

01 . All you wanted to know about FP* * And obviously you were too afraid to ask

Slide 19

Slide 19 text

19 History of Programming Paradigms 1957 FORTRAN Procedural programming COBOL would follow in 1959 and ALGOL in 1961 START 1947 A.R.C.2 Machine Assembly Kathleen and Andrew Donald Booth releases “Coding in A.R.C.”, which looks more like math; but it is the first mention to an “assembler” to program a machine.

Slide 20

Slide 20 text

20 1960 LISP Functional programming Based in the works of Lambda Calculus from 1930. 1967 SIMULA-1 & SMALLTALK Object-Oriented Programming Remember there’s still 16 years until C++ is released 28 years until Java is TBC

Slide 21

Slide 21 text

21 Functional programming is a paradigm where programs are constructed by applying and composing functions

Slide 22

Slide 22 text

22 A function is a computation that has an input and an output “ f: (A) -> B

Slide 23

Slide 23 text

Immutability Referential Transparency Recursion Lazy evaluation Pattern matching

Slide 24

Slide 24 text

Marketin g Purity Higher order

Slide 25

Slide 25 text

Pure functions fun sum(a: Int, b: Int): Int = a + b

Slide 26

Slide 26 text

Impure functions fun pureListAdd(list: List, element: E): List = list + element fun impureListAdd(list: MutableList, element: E): List { list.add(element) return list }

Slide 27

Slide 27 text

27 Higher order functions refers to the concept that a function can accept and/or return another function “ f: (A) -> B

Slide 28

Slide 28 text

28 Higher order functions refers to the concept that a function can accept and/or return another function “ f: ((C) -> D) -> (E)-> F

Slide 29

Slide 29 text

Simple example fun List.incr(): List { val result = mutableListOf() this.forEach {number -> result.add(number + 1) } return result } fun List.sqr(): List { val result = mutableListOf() this.forEach {number -> result.add(number * number) } return result }

Slide 30

Slide 30 text

Simple example interface Operation { fun execute(number: Int): Int } fun List.applyOp(op: Operation) : List { val result = mutableListOf() this.forEach {number -> result.add(op.execute(number)) } return result }

Slide 31

Slide 31 text

Simple example class Incr : Operation { override fun execute(number: Int): Int = number + 1 } class Sqr: Operation { override fun execute(number: Int): Int = number * number }

Slide 32

Slide 32 text

Simple example listOf(1,2,3).incr().sqr() // [4,9,16] listOf(1,2,3).applyOp(Incr()).applyOp(Sqr()) // [4,9, 16]

Slide 33

Slide 33 text

Simple example val incr = { number: Int -> number + 1 } val sqr = { number: Int -> number * number } fun List.applyOp(op: (Int) -> Int) : List { val result = mutableListOf() this.forEach {number -> result.add(op(number)) } return result } listOf(1,2,3).incr().sqr() // [4,9,16] listOf(1,2,3).applyOp(incr).applyOp(sqr) // [4,9,16]

Slide 34

Slide 34 text

Simple example val incr = { number: Int -> number + 1 } val sqr = { number: Int -> number * number } val incrAndSqr = { number: Int -> sqr(incr(number))} listOf(1,2,3).incr().sqr() // [4,9, 16] listOf(1,2,3).applyOp(incr).applyOp(sqr) // [4,9, 16] listOf(1,2,3).applyOp(incrAndSqr) // [4,9, 16]

Slide 35

Slide 35 text

02 . Warming up FP concepts

Slide 36

Slide 36 text

map zip flatmap

Slide 37

Slide 37 text

Slide 41

Slide 41 text

Slide 43

Slide 43 text

zip // map: ([A] ) -> [B] // zip: ([A],[B]) -> [(A, B)]

Slide 44

Slide 44 text

zip val nums = listOf(1, 2, 3) val letters = listOf("a", "b", "c") val lessLetters = listOf("a", "b") nums.zip(letters) // [(1, a), (2, b), (3, c)] nums.zip(lessLetters) // [(1, a), (2, b)]

Slide 45

Slide 45 text

zip val greenRoomSessions: Effect = effect { api.requestTalksFrom(greenRoomId) } val purpleRoomSessions: Effect = effect { api.requestTalksFrom(purpleRoomId) } greenRoomSessions.zip(purpleRoomSessions) // Effect .map { (purpleSessions, greenSessions) -> /*....*/ }

Slide 46

Slide 46 text

Slide 47

Slide 47 text

flatmap // map: ((A) -> B ) -> (([A]) -> [B]) // flatMap: ((A) -> [B]) -> (([A]) -> [B])

Slide 50

Slide 50 text

flatmap combo( listOf(1, 2, 3), listOf("a", "b", "c") ).flatMap { element: List> -> element.map { (num, letter) -> "$num$letter" } } // [1a, 1b, 1c, 2a...

Slide 51

Slide 51 text

flatmap fun List>.flatten() = flatMap(::id)

Slide 52

Slide 52 text

flatmap Effect { api.getSessionInfo(fpSessionId) } .flatmap { session -> Effect { api.getSpeakerInfo(session.speakerId) }} .map { speaker -> println(speaker.name)} // Saul Diaz

Slide 53

Slide 53 text

03 . The Monad

Slide 54

Slide 54 text

A monad is a monoid in the category of endofunctors “

Slide 55

Slide 55 text

A monad is a monoid in the category of endofunctors “ CONTAINER > same HAS MAP > >

Slide 56

Slide 56 text

A monad is a container that has map function to itself “

Slide 57

Slide 57 text

The monad // A monad is a Set (the mathematical one) such as // - Has an operation SxS -> S // - Has an element e: 1 -> S // That satisfies that // - a x (b x c) == (a x b) x c [associativity] // - e x a == a x e == a [left and right identity]

Slide 58

Slide 58 text

[ , , , ] The List

Slide 59

Slide 59 text

Simple example // Left identity val number = 5 val monad = listOf(5) val double = { value: Int -> listOf(value * 2)} val result = monad.flatMap(double) val result2 = double(number) println("$result == $result2") // [10] == [10]

Slide 60

Slide 60 text

Simple example // Right identity val wrapInList = { value: Int -> listOf(value) } val flatMapped = monad.flatMap(wrapInList) println("$monad == $flatMapped") // [5] == [5]

Slide 61

Slide 61 text

Simple example // Associativity val multiplyBy5 = { value: Int -> listOf(value * 5)} val multiplyBy10 = { value: Int -> listOf(value * 10) } val chained = monad.flatMap(multiplyBy5).flatMap(multiplyBy10) val nested = monad.flatMap{ multiplyBy5(it).flatMap(multiplyBy10) } println("$nested == $chained") // [250] == [250]

Slide 62

Slide 62 text

A monad is a container that wraps a type and provides a property the content does not have

Slide 65

Slide 65 text

04 . Lifting up

Slide 66

Slide 66 text

▸ As developers, knowing more tools will improve the number and quality of solutions we can apply to problems ▸ Leveraging OOP with FP can result in concise, understandable code with less boilerplate ▸ As OOP developers, we’ve been using more FP that we realized

Slide 67

Slide 67 text

67

Slide 68

Slide 68 text

Thanks! You can find me at [email protected] or @sefford at X Any questions?