Site icon Hari Vignesh

Functional Programming in Kotlin - f(2)

This is the second part of the functional programming series. If you have missed the previous one, start here.

Series pit stops

In this pit stop, we’ll take a brief look at how we write or represent a function in Kotlin. As a language what functional operations does Kotlin provide us out of the box? We’ll also see about pure functions.

Pre-requisites

Functions in Kotlin

As I presume that you already know that in Kotlin we define the function using the fun keyword. I also guess you have played the Kotlin drinking game - drink a shot each time when someone says fun in a Kotlin talk 😛

Jokes apart, Let’s take a look at some of the common functional operations on lists that Kotlin provides out of the box which we may have used in our everyday dev chores without actually realising or comparing it with functional paradigms.

Some of you may know the following functions, but the idea is to provide a different perspective on them when represented mathematically and to digest the functional concepts that we absorbed from the previous pit stop.

Dissecting map()

We would have used map frequently on lists in Kotlin. Usually mapping the list of items we receive from an API call to the view data. Let’s connect the dots with the knowledge we consumed from our previous pit stop. 

Representation of map

map(f: (A) -> B): List<B>
Kotlin

A functional instance, that takes in a function as an argument and applies to all the elements present in the list of A and provides us with the list of B

Mathematically:

        let set of A = { 1, 2, 3, 4, 5, 6 }
        given f(x) = x + 1

        map(f: (A) -> B) gives,

        f1: (1) -> 1 + 1 = 2
        f2: (2) -> 2 + 1 = 3
        ...

Programatically:

        val listA = listOf(1, 2, 3, 4, 5, 6)

        val listB = listA.map { x -> x + 1 } //print

        // output = [2, 3, 4, 5, 6, 7]
Kotlin

Fun Fact: When we say map takes a function as an argument, it’s actual representation is map({ x -> x + 1}). But in Kotlin, if the last argument is a function, we can remove the enclosing function brackets. That’s why we have map { x -> x + 1 }

Dissecting groupBy()

When we need to group or arrange our lists or mapped to one item, we use groupBy Representation of groupBy

groupBy(g: (C) -> D): Map<D, List<C>>
Kotlin

A functional instance, that takes in a function from C to D as an argument, applies the function to all the elements present in the list and returns a key value pair of list where the key being the type D and values of type C.

Mathematically:

        let set of C= { 1, 2, 3, 4, 5, 6 }
        given f(x) = x + 1

        groupBy(f: (C) -> D) gives,

        f1: (1) -> 1 + 1 = 2 and returns 2=[1] //key value pairs
        f2: (2) -> 2 + 1 = 3 and returns 3=[2]
        ...
        
Programatically:

        val listC = listOf(1, 2, 3, 4, 5, 6)
   
        val listD = listC.groupBy { x -> x + 1 } //print

        // output = {2=[1], 3=[2], 4=[3], 5=[4], 6=[5], 7=[6]}
Kotlin

Dissecting reduce()

We use this operation if we need to reduce the list into a single value. Representation of reduce

reduce(f: (E,E) -> E): E
Kotlin

A functional instance, that takes in a function by the operation (E, E) -> E, to reduce the list to a single value

Mathematically:

        let set of E= { 1, 2, 3, 4, 5, 6 }
        given f(x1, x2) = x1 + x2 // simply adding all the elements in E
   
        reduce(f: (E, E) -> E) gives,
   
        f1: (1, 2) -> 1 + 2 = 3 // which is x1 for f2
        f2: (3, 3) -> 3 + 3 = 6 // which is x1 for f3

Programatically:
    
        val listE = listOf(1, 2, 3, 4, 5, 6)

        val sumOfE = listE.reduce { first, second -> first + second }

        // output = 21
Kotlin

Pure Functions

If you recall, we kept mentioning multiple times that in order to make a function safe with less or no bugs, the function must be a pure function.

A function is considered as pure if it satisfies the following conditions (to put in a simple terms)

A function which does not satisfy the above conditions is called impure functions (We also have the partial function, currently out of scope for this post)

For better understanding, let’s analyse and classify the following functions as pure and impure

Example 1

fun division(x: double, y: Double): Double = x / y
Kotlin

The above function is pure as (let’s not consider overflow at the moment)

Example 2

fun addItems(value: Int, list: MutableList<Int>): List<Int> {
    list.add(value)
    return list
}
Kotlin

The above functions is impure as

Summary

Additional References


If you think you have learned something new or if you like this series or you want to boost my morale to publish the next pit stop fast, please share the post

Thanks a lot for reading this article. Stay tuned!!

Exit mobile version