Slide 1

Slide 1 text

LESS IMPERATIVE WITH MORE HUYEN TUE DAO @QUEENCODEMONKEY

Slide 2

Slide 2 text

Alright. Let’s talk terms.

Slide 3

Slide 3 text

IMPERATIVE PROGRAMMING a sequence of statements that change state.

Slide 4

Slide 4 text

focuses on actions. explicit control flow. IMPERATIVE PROGRAMMING

Slide 5

Slide 5 text

paradigm by which you describe how to do something. IMPERATIVE PROGRAMMING

Slide 6

Slide 6 text

100 REM FIND THE SUM OF THE TWO NUMBERS 200 LET X=9 300 LET Y=6 400 LET Z=X+Y 500 PRINT X,Y,Z 600 END

Slide 7

Slide 7 text

fun average(numbers: List): Float { var total = 0f for (i in 0 until numbers.size) { total += numbers[i] } return total / numbers.size }

Slide 8

Slide 8 text

DECLARATIVE PROGRAMMING describe what you want to do.

Slide 9

Slide 9 text

CAVEAT you or someone you encounter on StackOverflow may find this too fluffy, simplistic, imprecise, ambiguous. that’s okay. let’s keep this chill and practical.

Slide 10

Slide 10 text

DECLARATIVE PROGRAMMING describe what you want to do.

Slide 11

Slide 11 text

DECLARATIVE STYLE describe what you want to do.

Slide 12

Slide 12 text

Heyo, Foursquare!

What's up?

Slide 13

Slide 13 text

SELECT * FROM [Builds] WHERE [Efficacy] = 'OP'

Slide 14

Slide 14 text

fun average(numbers: List): Float {A var total = 0 forA(i in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A

Slide 15

Slide 15 text

fun average(numbers: List): Float {A val total = numbers.sum() return total.toFloat() / numbers.size }A

Slide 16

Slide 16 text

DECLARATIVE STYLE “…coding in the imperative style is like talking to a toddler.” Venkat Subramaniam

Slide 17

Slide 17 text

DECLARATIVE STYLE “The declarative version is like speaking to a responsible adult.” Venkat Subramaniam

Slide 18

Slide 18 text

Take your first left. Continue straight 2 miles. Slight right onto Raynor St. Left onto Kerrigan Ave. Continue straight .2 miles. DECLARATIVE IMPERATIVE My address is 8 Kerrigan Ave Reference, CO 88888 Tyler McGinnis “How do I get to your house from here?”

Slide 19

Slide 19 text

fun average(numbers: List): Float {A var total = 0 forA(i in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A

Slide 20

Slide 20 text

fun average(numbers: List): Float {A val total = numbers.sum() return total.toFloat() / numbers.size }A

Slide 21

Slide 21 text

FUNCTIONAL PROGRAMMING

Slide 22

Slide 22 text

FUNCTIONAL STYLE

Slide 23

Slide 23 text

FUNCTIONAL PROGRAMMING some disagreement on exact definition.

Slide 24

Slide 24 text

FUNCTIONAL PROGRAMMING style of programming based on evaluating functions

Slide 25

Slide 25 text

FUNCTIONAL PROGRAMMING style of programming based on evaluating f: x → f(x)

Slide 26

Slide 26 text

FUNCTIONAL PROGRAMMING style of programming based on evaluating expressions

Slide 27

Slide 27 text

STATEMENTS EXPRESSIONS computations. actions.

Slide 28

Slide 28 text

fun average(numbers: List): Float {A var total = 0 forA(i in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A

Slide 29

Slide 29 text

fun average(numbers: List): Float {A val total = numbers.sum() return total.toFloat() / numbers.size }A

Slide 30

Slide 30 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size

Slide 31

Slide 31 text

FUNCTIONAL PROGRAMMING mathematical, theoretical foundations. Category Theory. λ-calculus. many high-level and abstract concepts.

Slide 32

Slide 32 text

Let’s start with basic and practical, exploring a different way of thinking

Slide 33

Slide 33 text

var count = 1 fun calculate(x: Int, y: Int): Int {A count++ return x + y }A

Slide 34

Slide 34 text

what are side effects? SIDE EFFECTS when a function makes modifications of outside state

Slide 35

Slide 35 text

what are side effects? SIDE EFFECTS name sets them apart from main result of function.

Slide 36

Slide 36 text

fun calculateAndCache(x: Int, y: Int): Int { val value = x + y val sharedPrefs = getPreferences(Context.MODE_PRIVATE) sharedPrefs .edit() .putInt("lastValue", value) .apply() return value }

Slide 37

Slide 37 text

var count = 1 fun calculate(x: Int, y: Int): Int {A return x + y - count }A

Slide 38

Slide 38 text

fun calculate(x: Int, y: Int): Int { val value = x + y + resources.getInteger(R.integer.some_important_integer) return value }

Slide 39

Slide 39 text

when a function utilizes outside state or I/O SIDE CAUSES Kris Jenkins

Slide 40

Slide 40 text

when a function makes modifications of outside state SIDE EFFECTS

Slide 41

Slide 41 text

when a function interacts with the outside world SIDE EFFECTS

Slide 42

Slide 42 text

SIDE EFFECTS “Wait. Isn’t that just programming?”

Slide 43

Slide 43 text

SIDE EFFECTS apps need to interact with the outside world

Slide 44

Slide 44 text

Here comes the “but”…

Slide 45

Slide 45 text

make code harder to trace and understand. SIDE EFFECTS

Slide 46

Slide 46 text

make code harder to test and debug. have to re-create the environment. SIDE EFFECTS

Slide 47

Slide 47 text

therefore, can be a source of bugs. SIDE EFFECTS

Slide 48

Slide 48 text

but we need them. so we want to limit and control them. SIDE EFFECTS

Slide 49

Slide 49 text

FUNCTIONAL PROGRAMMING style of programming based on evaluating expressions

Slide 50

Slide 50 text

FUNCTIONAL PROGRAMMING “Functional code is characterised by one thing: the absence of side effects.” Mary Rose Cook

Slide 51

Slide 51 text

FUNCTIONAL PROGRAMMING “Every other ‘functional’ thing can be derived from this property.” Mary Rose Cook

Slide 52

Slide 52 text

FUNCTIONAL PROGRAMMING No side effects. Immutability. Higher-order functions. Kotlin in Action

Slide 53

Slide 53 text

FUNCTIONAL PROGRAMMING No side effects. Immutability. Higher-order functions. Kotlin in Action

Slide 54

Slide 54 text

result depends only on the inputs. there are no side effects. PURE FUNCTIONS

Slide 55

Slide 55 text

idempotent function that has the property that: f(f(x)) → f(x) PURE FUNCTIONS

Slide 56

Slide 56 text

idempotent multiple calls with same inputs has same effect as one call. PURE FUNCTIONS

Slide 57

Slide 57 text

var count = 0 fun increment() { count++ // count = 1 count++ // count = 2 count++ // count = 3 count++ // count = 4 }

Slide 58

Slide 58 text

nullipotent calling function zero times has same effect as calling it once. PURE FUNCTIONS

Slide 59

Slide 59 text

referential transparency an expression or function may be safely replaced by its value. PURE FUNCTIONS

Slide 60

Slide 60 text

var count = 0 fun calculate(x: Int, y: Int): Int {A return x + y }A val result = calculate(1, 2) // result = 3, count = 0

Slide 61

Slide 61 text

var count = 0 fun calculate(x: Int, y: Int): Int { return x + y }A val result = 3 // result = 3, count = 0

Slide 62

Slide 62 text

var count = 0 fun calculate(x: Int, y: Int): Int {A count++ return x + y }A val result = calculate(1, 2) // result = 3, count = 1

Slide 63

Slide 63 text

var count = 0 fun calculate(x: Int, y: Int): Int {A count++ return x + y }A val result = 3 // result = 3, count = 0

Slide 64

Slide 64 text

referential transparency an expression or function may be safely replaced by its value. PURE FUNCTIONS

Slide 65

Slide 65 text

Absence of side effects. PURE FUNCTIONS

Slide 66

Slide 66 text

Encourages separation of concerns. PURE FUNCTIONS

Slide 67

Slide 67 text

Easier to understand and test. PURE FUNCTIONS

Slide 68

Slide 68 text

FUNCTIONAL PROGRAMMING No side effects. Immutability. Higher-order functions. Kotlin in Action

Slide 69

Slide 69 text

FUNCTIONAL PROGRAMMING No side effects. Immutability. Higher-order functions. Kotlin in Action

Slide 70

Slide 70 text

FUNCTIONAL PROGRAMMING No side effects. Immutability. Higher-order functions. Kotlin in Action

Slide 71

Slide 71 text

So what are the benefits?

Slide 72

Slide 72 text

Easier to understand.

Slide 73

Slide 73 text

More concise.

Slide 74

Slide 74 text

More maintainable.

Slide 75

Slide 75 text

Easier testing.

Slide 76

Slide 76 text

Safer multithreading.

Slide 77

Slide 77 text

Less error-prone.

Slide 78

Slide 78 text

FUNCTIONAL BITS OF

Slide 79

Slide 79 text

FUNCTIONAL BITS OF function types + lambdas.

Slide 80

Slide 80 text

FUNCTIONAL BITS OF data classes + immutable collections

Slide 81

Slide 81 text

FUNCTIONAL BITS OF functional style APIs in the stdlib

Slide 82

Slide 82 text

FUNCTIONAL BITS OF functional is not required. can live next to imperative and OOP code.

Slide 83

Slide 83 text

Let’s start thinking functionally with .

Slide 84

Slide 84 text

fun average(numbers: List): Float {A val total = numbers.sum() return total.toFloat() / numbers.size }A

Slide 85

Slide 85 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size

Slide 86

Slide 86 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size immutability

Slide 87

Slide 87 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size pure function

Slide 88

Slide 88 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size pure function depends only on input same inputs yield same output

Slide 89

Slide 89 text

fun average(numbers: List) = numbers.sum().toFloat() / numbers.size

Slide 90

Slide 90 text

fun average(numbers: List) = numbers.average()

Slide 91

Slide 91 text

stdlib is full of functional operators.

Slide 92

Slide 92 text

functional operators are awesome.

Slide 93

Slide 93 text

let’s talk about mapping.

Slide 94

Slide 94 text

val films = listOf( Movie("Beauty and the Beast", 2017, 504.1f), Movie("Guardians of the Galaxy Vol. 2", 2017, 389.8f), Movie("Dunkirk", 2017, 188.5f), Movie("Rogue One", 2016, 532.18f), Movie("Finding Dory", 2016, 486.30f), Movie("Deadpool", 2016, 363.07f), Movie("Fantastic Beasts and Where to Find Them", 2016, 234.04f), Movie("Hidden Figures", 2016, 169.39f), Movie("Star Wars: The Force Awakens", 2015, 936.66f), Movie("Jurassic World", 2015, 652.27f), Movie("Avengers: Age of Ultron", 2015, 459.01f), Movie("Inside Out", 2015, 356.46f) )

Slide 95

Slide 95 text

fun getFilmTitles(films: List): List {A val names = mutableListOf() for (film in films) { names.add(film.name) } return names }A

Slide 96

Slide 96 text

fun getFilmTitles(films: List): List {A return films.map { film -> film.name } }A

Slide 97

Slide 97 text

fun getFilmTitles(films: List): List {A return films.map { film -> film.name } }A

Slide 98

Slide 98 text

Iterable.map(transform: (T) -> R): List

Slide 99

Slide 99 text

extension function Iterable.map(transform: (T) -> R): List

Slide 100

Slide 100 text

Iterable.map(transform: (T) -> R): List immutability

Slide 101

Slide 101 text

Iterable.map(transform: (T) -> R): List higher-order function

Slide 102

Slide 102 text

fun getFilmTitles(films: List): List {A val names = mutableListOf() for (film in films) { names.add(film.name) } return names }A

Slide 103

Slide 103 text

fun getFilmTitles(films: List): List {A return films.map { film -> film.name } }A let’s sprinkle on some sugar.

Slide 104

Slide 104 text

fun getFilmTitles(films: List) = films.map { it.name }

Slide 105

Slide 105 text

fun getFilmTitles(films: List) = films.map { it.name } expression body implicit single parameter name

Slide 106

Slide 106 text

fun getFilmTitles(films: List) = films.map { it.name }

Slide 107

Slide 107 text

fun getFilmTitles(films: List) = films.map(Movie::name) property reference

Slide 108

Slide 108 text

let’s talk about folding.

Slide 109

Slide 109 text

fun totalGross(films: List): Float { var gross:Float = 0f for (film in films) { gross += film.gross } return gross }

Slide 110

Slide 110 text

fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 111

Slide 111 text

fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 112

Slide 112 text

fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R

Slide 113

Slide 113 text

fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R pure function

Slide 114

Slide 114 text

fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R extension function

Slide 115

Slide 115 text

fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R immutability

Slide 116

Slide 116 text

fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R higher-order function

Slide 117

Slide 117 text

fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 118

Slide 118 text

fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 119

Slide 119 text

fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 120

Slide 120 text

let’s sprinkle on some sugar. fun totalGross(films: List): Float { return films.fold(0f) { gross, film -> gross + film.gross } }

Slide 121

Slide 121 text

fun totalGross(films: List) = films.sumByDouble { movie -> movie.gross.toDouble() }

Slide 122

Slide 122 text

let’s talk about filtering.

Slide 123

Slide 123 text

fun moviesFrom2017(films: List): List { val results = mutableListOf() for (film in films) { if (film.year == 2017) { results.add(film) } } return results }

Slide 124

Slide 124 text

fun moviesFrom2017(films: List) = films.filter { it.year == 2017 }

Slide 125

Slide 125 text

fun moviesFrom2017(films: List) = films.filter { it.year == 2017 }

Slide 126

Slide 126 text

fun Iterable.filter(predicate: (T) -> Boolean): List

Slide 127

Slide 127 text

fun Iterable.filter(predicate: (T) -> Boolean): List pure function

Slide 128

Slide 128 text

fun Iterable.filter(predicate: (T) -> Boolean): List immutability

Slide 129

Slide 129 text

fun Iterable.filter(predicate: (T) -> Boolean): List higher-order function

Slide 130

Slide 130 text

fun moviesFrom2017(films: List) = films.filter { it.year == 2017 }

Slide 131

Slide 131 text

println("2016 Films = ${films.filter { it.year == year }}")

Slide 132

Slide 132 text

val greaterThan100M = { movie: Movie -> movie.gross > 100.0f } println("2016 Films = ${films.filter(greaterThan100M)}") starting to look like a strategy pattern

Slide 133

Slide 133 text

val greaterThan100M = { movie: Movie -> movie.gross > 100.0f } println("2016 Films = ${films.filter(greaterThan100M)}") starting to look like a strategy pattern

Slide 134

Slide 134 text

now for some composition.

Slide 135

Slide 135 text

val names = films .filter { it.year == 2016 && it.gross > 100f } .map { it.name } println("Name of 2016 Films Grossing More Than $100M = $names")

Slide 136

Slide 136 text

experiment with creating declarative structures.

Slide 137

Slide 137 text

interface Map V computeIfAbsent(K key, Function mappingFunction) V computeIfPresent(K key, Function mappingFunction) let’s make our own and sprinkle on function types

Slide 138

Slide 138 text

inline fun MutableMap.computeIf(key: K, predicate: (K, V?) -> Boolean, mappingFunction: (K, V?) -> V?): V? { val oldValue = get(key) if (!predicate(key, oldValue)) return oldValue val newValue = mappingFunction(key, oldValue) if (newValue == oldValue) return newValue if (newValue != null) put(key, newValue) else if (oldValue != null) remove(key) return newValue }

Slide 139

Slide 139 text

inline fun MutableMap.computeIf(key: K, predicate: (K, V?) -> Boolean, mappingFunction: (K, V?) -> V?): V? { val oldValue = get(key) if (!predicate(key, oldValue)) return oldValue val newValue = mappingFunction(key, oldValue) if (newValue == oldValue) return newValue if (newValue != null) put(key, newValue) else if (oldValue != null) remove(key) return newValue } extension function

Slide 140

Slide 140 text

inline fun MutableMap.computeIf(key: K, predicate: (K, V?) -> Boolean, mappingFunction: (K, V?) -> V?): V? { val oldValue = get(key) if (!predicate(key, oldValue)) return oldValue val newValue = mappingFunction(key, oldValue) if (newValue == oldValue) return newValue if (newValue != null) put(key, newValue) else if (oldValue != null) remove(key) return newValue } functions as inputs

Slide 141

Slide 141 text

inline fun MutableMap.computeIf(key: K, predicate: (K, V?) -> Boolean, mappingFunction: (K, V?) -> V?): V? { val oldValue = get(key) if (!predicate(key, oldValue)) return oldValue val newValue = mappingFunction(key, oldValue) if (newValue == oldValue) return newValue if (newValue != null) put(key, newValue) else if (oldValue != null) remove(key) return newValue } all mutability hidden inside

Slide 142

Slide 142 text

inline fun MutableMap.computeIf(key: K, predicate: (K, V?) -> Boolean, mappingFunction: (K, V?) -> V?): V? { val oldValue = get(key) if (!predicate(key, oldValue)) return oldValue val newValue = mappingFunction(key, oldValue) if (newValue == oldValue) return newValue if (newValue != null) put(key, newValue) else if (oldValue != null) remove(key) return newValue } blending programming paradigms

Slide 143

Slide 143 text

cachedConfigs.computeIf( "KittiesOnDemandFeature", { key, previous -> previous?.json != kittyJson }, { key, previous -> FeatureConfig.from(kittyJson) } )

Slide 144

Slide 144 text

THANK YOU! SPEAKERDECK.COM/QUEENCODEMONKEY YOUTUBE.COM/ANDROIDDIALOGS RANDOMLYTYPING.COM HUYEN TUE DAO @QUEENCODEMONKEY

Slide 145

Slide 145 text

val result = x + y computation

Slide 146

Slide 146 text

val result = x + y action

Slide 147

Slide 147 text

REFERENCES 147 Wikipedia: Functional Programming | wikipedia.org/wiki/Functional_programming Functional Programming | https://wiki.haskell.org/Functional_programming What Is Functional Programming? | blog.jenkster.com/2015/12/what-is-functional-programming.html | @krisajenkins An introduction to functional programming | codewords.recurse.com/issues/one/an-introduction-to-functional-programming | @maryrosecook Imperative vs. Declarative Programming | https://tylermcginnis.com/imperative-vs-declarative-programming/ | @tylermcginnis Imperative Style | http://blog.agiledeveloper.com/2015/07/the-imperative-style.html | @venkat_s Declarative Style | http://blog.agiledeveloper.com/2015/07/the-declarative-style.html | @venkat_s Functional Style | http://blog.agiledeveloper.com/2015/08/the-functional-style.html | @venkat_s Benefits of Pure Functions: Offer Referential Transparency | blog.agiledeveloper.com/2016/01/benefits-of-pure-functions-offer.html | @venkat_s Functional Programming Favors Expressions over Statements | http://blog.agiledeveloper.com/2015/08/functional-programming- favors.html | @venkat_s What is function programming? | https://www.quora.com/What-is-functional-programming

Slide 148

Slide 148 text

REFERENCES 148 Kotlin in Action | manning.com/books/kotlin-in-action WikiWikiWeb | wiki.c2.com/ Why Functional Programming Matters | https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf | John Hughes, The University, Glasgow Kotlin purity and function memoization | https://medium.com/@JorgeCastilloPr/kotlin-purity-and-function-memoization- b12ab35d70a5 Kotlin Functional Programming: Does it make sense? | medium.com/@JorgeCastilloPr/kotlin-functional-programming-does-it-make- sense-36ad07e6bacf | @JorgeCastilloPr Functional, Declarative, Imperative Programming [closed] | https://stackoverflow.com/questions/602444/functional-declarative-and- imperative-programming What are monads in functional programming and why are they useful? | https://www.quora.com/What-are-monads-in-functional- programming-and-why-are-they-useful-Are-they-a-generic-solution-to-the-problem-of-state-in-FP-or-Haskell-specific-Are-they- specific-to-Haskell-or-are-they-encountered-in-other-FP-languages