Functional Programming on Android: is it possible?
About • Android Developer @ M4U • Organizer @ Kotlin Rio Meetup Github: https://github.com/lalbuquerque Linkedin: www.linkedin.com/in/lucasalbuquerque Email: lucas.albuquerque12@gmail.com
TALK “FUNCTIONAL PROGRAMMING ON ANDROID: IS IT POSSIBLE?” someData.map(it + 2) .filter(it > 10) .sort(…) .reduce(…) .group(…) .flatMap(…) .just(…) .jointTo(…) .fold(…) .slice(…) .takeLastWhile(…) EXPECTATION data class MyObject(val name: String) REALITY
https://msdn.microsoft.com/en-us/library/hh242985(v=vs.103).aspx
"Functional code is characterised by one thing: the absence of side effects. It doesn’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. Every other “functional” thing can be derived from this property. Use it as a guide rope as you learn.” - - Mary Rose Cook - https://maryrosecook.com/blog/post/a-practical-introduction-to-functional- programming
SO I CAN GO FUNCTIONAL WITH JAVA?
Lisp | John McCarthy and Steve Russell | 1958
Immutability
Read-Modify-Write
class Car(var noOfDrivers: Int)
class Car(val noOfDrivers: Int)
Using functions right
"A pure function is a function that, given the same input, will always return the same output and does not have any observable side effect." - Professor Franklin Risby's - Mostly Adequate Guide to Functional Programming
fun add(x: Int): Int { val y: Int = readNumFromFile() return x + y } Impure
fun add(x: Int, y: Int) = x + y Pure
fun plus2(x: Int): Int { val y = x + 2 cache(y) return y } Impure
fun plus2(x: Int) = x + 2 Pure
"The name of a variable, function or class should answer the big questions such as why it exists, what it does, how it is used." Aiden Mc Raft commenting Robert C. Martin’s Clean Code: A Handbook of Agile Software Craftsmanship
Demystifying functions
fun add(x: Int, y: Int) = x + y
val add = fun add(x: Int, y: Int) = x + y
fun doSomething(function: (Int, Int) -> Int) { … }
data class User(val name: String, val amount: Int, val onClick: (User) -> Unit)
with(user) { holder.itemView.setOnClickListener { onClick(this) } }
enum class Operation { ADD, SUB }
fun applyOperation(operation: Operation): (Int, Int) -> Int { val add = fun (x: Int, y: Int) = x + y val sub = fun (x: Int, y: Int) = x - y when (operation) { Operation.ADD -> return add Operation.SUB -> return sub } }
applyOperation(Operation.ADD) (1, 3)
Functional Operators
public inline fun <T, R> …Iterable<T>.map(transform: (T) -> (R)): …List<R> val myList = listOf(2, 4, 6, 8, 10, 12) val myNewList = myList.map { it * 2 } // [ 4, 8, 12, 16, 20, 24 ]
none(…) val myList = listOf(2, 4, 6, 8, 10, 12) myList.none { it % 7 == 0 } // true
filter(…) val myList = listOf(4, 8, 12, 16, 20, 24) myList.filter { it > 20 } // [ 24 ]
forEach(…) val myList = listOf(2, 4, 6, 8, 10, 12) myList.forEach { Log.i(TAG, it.toString() }
fun returnBiggerNames(names: MutableList<String>): MutableList<String> { names .filter { it.length < 10 } .forEach { names.remove(it) } return names } Impure
fun returnBiggerNames(names: List<String>) = names.filter { it.length > 10 } Pure
public List<ContributorCount> getContributorCounts(List<ArticleView> articleViews) { HashMap<String, Integer> contributorCounts = new HashMap<String, Integer>(); for (ArticleView articleView : articleViews) { Integer count = contributorCounts.get(articleView.contributor); if (count == null) contributorCounts.put(articleView.contributor, 1); else contributorCounts.put(articleView.contributor, count + 1); } List<ContributorCount> result = new ArrayList<ContributorCount>(); for (String contributor : contributorCounts.keySet()) { int count = contributorCounts.get(contributor); if (count > 1) result.add(new ContributorCount(contributor, contributorCounts.get(contributor))); } return result; }
fun getContributorCounts(views: List<ArticleView>) = views.groupBy { it.contributor } .mapValues { it.value.size }   .filter { it.value > 1 } .map { ContributorCount(it.key, it.value) }
Recursion
fun cosFixpoint(x: Double = 1.0): Double { while (true) { val y = Math.cos(x) if (x == y) return y x = y } }
tailrec fun cosFixpoint(x: Double = 1.0): Double { val y = Math.cos(x) return if (x == y) x else cosFixpoint(y) }
tailrec fun f(x: Double = 1.0): Double = if (x == cos(x)) x else f(cos(x)))
Thank you!
Bibliography 1. https://drboolean.gitbooks.io/mostly-adequate-guide 2. https://www.theguardian.com/info/developer-blog/2014/dec/ 11/functional-android 3. https://medium.com/@anupcowkur/functional-programming- for-android-developers-part-3-f9e521e96788 4. https://blog.plan99.net/kotlin-fp-3bf63a17d64a

Functional Programming on Android: is it possible?