Huyen Tue Dao
December 13, 2017
230

# 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

1. LESS IMPERATIVE
WITH MORE
HUYEN TUE DAO
@QUEENCODEMONKEY

2. Alright. Let’s talk terms.

3. IMPERATIVE
PROGRAMMING
a sequence of statements that
change state.

4. focuses on actions.
explicit control flow.
IMPERATIVE
PROGRAMMING

describe how to do something.
IMPERATIVE
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): Float {
var total = 0f
for (i in 0 until numbers.size) {
total += numbers[i]
}
}

8. DECLARATIVE
PROGRAMMING
describe what you want to do.

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.

10. DECLARATIVE
PROGRAMMING
describe what you want to do.

11. DECLARATIVE
STYLE
describe what you want to do.

12. Heyo, Foursquare!
What's up?

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

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

15. fun average(numbers: List): Float {A
val total = numbers.sum()
}A

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

17. DECLARATIVE
STYLE
“The declarative version is like
Venkat Subramaniam

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

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

20. fun average(numbers: List): Float {A
val total = numbers.sum()
}A

21. FUNCTIONAL
PROGRAMMING

22. FUNCTIONAL
STYLE

23. FUNCTIONAL
PROGRAMMING
some disagreement on exact definition.

24. FUNCTIONAL
PROGRAMMING
style of programming based on
evaluating functions

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

26. FUNCTIONAL
PROGRAMMING
style of programming based on
evaluating expressions

27. STATEMENTS
EXPRESSIONS
computations.
actions.

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

29. fun average(numbers: List): Float {A
val total = numbers.sum()
}A

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

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

basic and practical,
exploring a different
way 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
}

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

40. when a function makes
modifications of outside state
SIDE EFFECTS

41. when a function interacts
with the outside world
SIDE EFFECTS

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

43. SIDE EFFECTS
apps need to interact
with the outside world

44. Here comes the “but”…

45. make code harder
to trace and understand.
SIDE EFFECTS

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

47. therefore, can be a source of bugs.
SIDE EFFECTS

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

49. FUNCTIONAL
PROGRAMMING
style of programming based on
evaluating expressions

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

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

53. FUNCTIONAL
PROGRAMMING
No side effects.
Immutability.
Higher-order functions.
Kotlin in 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

65. Absence of side effects.
PURE FUNCTIONS

66. Encourages separation of concerns.
PURE FUNCTIONS

67. Easier to understand and test.
PURE FUNCTIONS

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

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

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

71. So what are the
benefits?

72. Easier to understand.

73. More concise.

74. More maintainable.

75. Easier testing.

77. Less error-prone.

78. FUNCTIONAL
BITS OF

79. FUNCTIONAL
BITS OF
function types + lambdas.

80. FUNCTIONAL
BITS OF
data classes + immutable collections

81. FUNCTIONAL
BITS OF
functional style APIs in the stdlib

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

83. Let’s start thinking
functionally with .

84. fun average(numbers: List): Float {A
val total = numbers.sum()
}A

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

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

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

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

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

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

91. stdlib is full of
functional operators.

92. functional operators
are awesome.

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("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): List {A
val names = mutableListOf()
for (film in films) {
}
return names
}A

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

134. now for some composition.

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

136. experiment with creating
declarative structures.

137. interface Map
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 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
}

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

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

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

142. 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
}

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

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

145. val result = x + y
computation

146. val result = x + y
action

147. REFERENCES
147
Wikipedia: Functional Programming | wikipedia.org/wiki/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-