Kotlin High Order Functions and Lambdas Explained

A higher-order function is a function that takes functions as parameters or returns a function. Instead of Integer, String, or Array as a parameter to a function, we will pass an anonymous function or lambdas. Frequently, lambdas are passed as parameters in Kotlin functions for convenience.

before getting started into scope functions, I have explained the basics of kotlin in detail.

Beginning Android Development with Kotlin

Kotlin Scope Functions Explained

Kotlin Coroutines for Android Development

koin – Kotlin Dependency Injection In Android

Ktor – Networking Client For Android

This can be achieved by using lambda expressions or function references.

Function Types

Kotlin uses function types to represent the type of a function.

The syntax of a function type is,

(Type, Type) -> ReturnType</pre>

with the left side containing the parameter types and the right side the return type. For empty returns, you can use Unit.

Function types can be instantiated in a multitude of ways. Let’s look at some of them.

  • Lambda expressions
  • Anonymous functions
  • Existing function

Lambda expressions

The full syntactic form of lambda expressions is as follows:

val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
  • A lambda expression is always surrounded by curly braces.
  • Parameter declarations in the full syntactic form go inside curly braces and have optional type annotations.
  • The body goes after the ->.
  • If the inferred return type of the lambda is not Unit, the last (or possibly single) expression inside the lambda body is treated as the return value.

If you leave all the optional annotations out, what’s left looks like this:

val sum = { x: Int, y: Int -> x + y }

It’s very common for a lambda expression to have only one parameter.

If the compiler can parse the signature without any parameters, the parameter does not need to be declared and -> can be omitted. The parameter will be implicitly declared under the name it:

ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'

Returning a value from a lambda expression

You can explicitly return a value from the lambda using the qualified return syntax. Otherwise, the value of the last expression is implicitly returned.

Underscore for unused variables

If the lambda parameter is unused, you can place an underscore instead of its name:

map.forEach { _, value -> println("$value!") }

Anonymous functions

An anonymous function looks very much like a regular function declaration, except its name is omitted. Its body can be either an expression (as shown above) or a block:

Anonymous functions as an expression

fun(x: Int, y: Int): Int = x + y

Anonymous functions as a block.

fun(x: Int, y: Int): Int {
    return x + y
}

Existing function

Member functions, top-level functions, or extension functions can be used as an instance of a function type. As an example, getting a reference to the String. Any other function declarations, even constructors can be used.

 val filter = String::filter

Higher Order Functions

A higher-order function is a function that takes functions as parameters or returns a function.

It’s a function that can take do two things:

  • Can take functions as parameters
  • Can return a function

We will see both things one by one.

Take functions as parameters

fun getUserDetail(user: () -> Unit) {
    ...
    user()
}

function getUserDetail takes user: () -> Unit .

user is just the name for the parameter. It can be anything. We just need to use this when we execute the function.

() -> Unit, this is important.

() represents that the function takes no parameters.

The unit represents that the function does not return anything.

So, the getUserDetail can take a function that takes zero parameters and does not return anything.

Let’s try the getUserDetail function without arguments.

fun main() {

    fun getUserDetail(user: () -> Unit) {
        user()
        println("Address: chennai")
    }

    getUserDetail({
        println("name : joe")
        println("age : 25")
    })
}

next, we can see the same function getUserDetail with arguments.

fun main() {

    fun getUserDetail(user: (String, Int) -> Unit) {
        user("joe", 25)
        println("Address: chennai")
    }

    getUserDetail({name, age ->
        println("name : joe")
        println("age : 25")
    })
}

function getUserDetail(user: (String, Int) -> Unit)

(String, Int) – represent the functions takes two arguments.

The Unit represents that the function does not return anything.

A function can return a function

We can return a function from a higher-order function. While returning the function, we have to specify the parameter types and return types of the regular functions in the return type of the higher-order function.

fun main() {

    fun getUserDetail() : ((String) -> Unit) {

        return ::getUser
    }

    val userDetail = getUserDetail()
    userDetail("john")
}

fun getUser(name: String) : Unit {
    println(name)
}

function fun getUserDetail() : ((String) -> Unit)

: (String) – represent the return functions that takes one argument.

: () -> Unit– the Unit represent the function return nothing.

::getUser – represents the function return getUser function.

In the main function, we have called the higher function which returns another function and stores this in a variable user detail.

val userDetail = getUserDetail()
userDetail("john")

then we invoke the userDetail() function using a local variable userDetail("john") by passing one argument.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


Latest Posts