Huyen Tue Dao
December 13, 2017
250

# Less Imperative with More Kotlin

Huyen's talk given at a Night Discussing Kotlin @ Foursquare HQ discussing basic definitions and terms related to Functional Programming and relating them to Kotlin.

## Huyen Tue Dao

December 13, 2017

## Transcript

PROGRAMMING
6. ### 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
7. ### fun average(numbers: List<Int>): Float { var total = 0f for

(i in 0 until numbers.size) { total += numbers[i] } return total / numbers.size }

9. ### 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.

14. ### fun average(numbers: List<Int>): Float {A var total = 0 forA(i

in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A
15. ### fun average(numbers: List<Int>): Float {A val total = numbers.sum() return

total.toFloat() / numbers.size }A
16. ### DECLARATIVE STYLE “…coding in the imperative style is like talking

to a toddler.” Venkat Subramaniam

18. ### 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?”
19. ### fun average(numbers: List<Int>): Float {A var total = 0 forA(i

in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A
20. ### fun average(numbers: List<Int>): Float {A val total = numbers.sum() return

total.toFloat() / numbers.size }A

→ f(x)

28. ### fun average(numbers: List<Int>): Float {A var total = 0 forA(i

in 0Auntil numbers.size) { total += numbers[i] } return total.toFloat() / numbers.size }A
29. ### fun average(numbers: List<Int>): Float {A val total = numbers.sum() return

total.toFloat() / numbers.size }A

31. ### FUNCTIONAL PROGRAMMING mathematical, theoretical foundations. Category Theory. λ-calculus. many high-level

and abstract concepts.

of thinking
33. ### var count = 1 fun calculate(x: Int, y: Int): Int

{A count++ return x + y }A
34. ### what are side effects? SIDE EFFECTS when a function makes

modifications of outside state
35. ### what are side effects? SIDE EFFECTS name sets them apart

from main result of function.
36. ### 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 }
37. ### var count = 1 fun calculate(x: Int, y: Int): Int

{A return x + y - count }A
38. ### fun calculate(x: Int, y: Int): Int { val value =

x + y + resources.getInteger(R.integer.some_important_integer) return value }

Kris Jenkins

46. ### make code harder to test and debug. have to re-create

the environment. SIDE EFFECTS

48. ### but we need them. so we want to limit and

control them. SIDE EFFECTS

50. ### FUNCTIONAL PROGRAMMING “Functional code is characterised by one thing: the

absence of side effects.” Mary Rose Cook
51. ### FUNCTIONAL PROGRAMMING “Every other ‘functional’ thing can be derived from

this property.” Mary Rose Cook

Action

Action
54. ### result depends only on the inputs. there are no side

effects. PURE FUNCTIONS
55. ### idempotent function that has the property that: f(f(x)) → f(x)

PURE FUNCTIONS
56. ### idempotent multiple calls with same inputs has same effect as

one call. PURE FUNCTIONS
57. ### var count = 0 fun increment() { count++ // count

= 1 count++ // count = 2 count++ // count = 3 count++ // count = 4 }
58. ### nullipotent calling function zero times has same effect as calling

it once. PURE FUNCTIONS
59. ### referential transparency an expression or function may be safely replaced

by its value. PURE FUNCTIONS
60. ### var count = 0 fun calculate(x: Int, y: Int): Int

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

{ return x + y }A val result = 3 // result = 3, count = 0
62. ### 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
63. ### var count = 0 fun calculate(x: Int, y: Int): Int

{A count++ return x + y }A val result = 3 // result = 3, count = 0
64. ### referential transparency an expression or function may be safely replaced

by its value. PURE FUNCTIONS

Action

Action

Action

82. ### FUNCTIONAL BITS OF functional is not required. can live next

to imperative and OOP code.

84. ### fun average(numbers: List<Int>): Float {A val total = numbers.sum() return

total.toFloat() / numbers.size }A

88. ### fun average(numbers: List<Int>) = numbers.sum().toFloat() / numbers.size pure function depends

only on input same inputs yield same output

94. ### 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) )
95. ### fun getFilmTitles(films: List<Movie>): List<String> {A val names = mutableListOf<String>() for

(film in films) { names.add(film.name) } return names }A
96. ### fun getFilmTitles(films: List<Movie>): List<String> {A return films.map { film ->

film.name } }A
97. ### fun getFilmTitles(films: List<Movie>): List<String> {A return films.map { film ->

film.name } }A

102. ### fun getFilmTitles(films: List<Movie>): List<String> {A val names = mutableListOf<String>() for

(film in films) { names.add(film.name) } return names }A
103. ### fun getFilmTitles(films: List<Movie>): List<String> {A return films.map { film ->

film.name } }A let’s sprinkle on some sugar.

105. ### fun getFilmTitles(films: List<Movie>) = films.map { it.name } expression body

implicit single parameter name

109. ### fun totalGross(films: List<Movie>): Float { var gross:Float = 0f for

(film in films) { gross += film.gross } return gross }
110. ### fun totalGross(films: List<Movie>): Float { return films.fold(0f) { gross, film

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

-> gross + film.gross } }

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

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

extension function

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

higher-order function
117. ### fun totalGross(films: List<Movie>): Float { return films.fold(0f) { gross, film

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

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

-> gross + film.gross } }
120. ### let’s sprinkle on some sugar. fun totalGross(films: List<Movie>): Float {

return films.fold(0f) { gross, film -> gross + film.gross } }

123. ### fun moviesFrom2017(films: List<Movie>): List<Movie> { val results = mutableListOf<Movie>() for

(film in films) { if (film.year == 2017) { results.add(film) } } return results }

132. ### val greaterThan100M = { movie: Movie -> movie.gross > 100.0f

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

} println("2016 Films = \${films.filter(greaterThan100M)}") starting to look like a strategy pattern

135. ### val names = films .filter { it.year == 2016 &&

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

137. ### interface Map<K, V> V computeIfAbsent(K key, Function<? super K,? extends

V> mappingFunction) V computeIfPresent(K key, Function<? super K,? extends V> mappingFunction) let’s make our own and sprinkle on function types
138. ### inline fun <K, V> MutableMap<K, V>.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 }
139. ### inline fun <K, V> MutableMap<K, V>.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
140. ### inline fun <K, V> MutableMap<K, V>.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
141. ### inline fun <K, V> MutableMap<K, V>.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
142. ### inline fun <K, V> MutableMap<K, V>.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
143. ### cachedConfigs.computeIf( "KittiesOnDemandFeature", { key, previous -> previous?.json != kittyJson },

{ key, previous -> FeatureConfig.from(kittyJson) } )

147. ### 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 Beneﬁts of Pure Functions: Offer Referential Transparency | blog.agiledeveloper.com/2016/01/beneﬁts-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
148. ### 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://stackoverﬂow.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-speciﬁc-Are-they- speciﬁc-to-Haskell-or-are-they-encountered-in-other-FP-languages