Kotlin: Function type, Function literal, Lambda expression and Anonymous function

srdpatel

Sagar

Posted on May 1, 2020

Kotlin: Function type, Function literal, Lambda expression and Anonymous function

Function Type

We know data types. Similarly, we have function type too in kotlin.

Signature / Syntax

    Name: (only comma separated data types) -> return data type

    ft: (Int, Int) -> Int

How to call / execute a function type?

    ft(1, 2) 

    //OR

    ft.invoke(1, 2)

Usage:

Function type as an interface

Like an interface, we can implement a function type in a kotlin class. When we implement a function type, we get a method called “invoke” to override having a similar signature of the implemented function type.

Example:

    //Implementing a function type like an interface
    class ClassName : (Int, Int) -> Int {

    /**We get a method "invoke" to override with similar signature of     
     * function type we implemented
     */
    override fun invoke(p1: Int, p2: Int): Int {
            return p1 + p2
        }

    }

Function type as a parameter

As a function parameter in a higher order function. The function that takes one or more function types as a parameter/s or/and the function that returns a function type is known as a higher order function.

    fun doSomething(a: Int, b: Int, ft: (Int, Int) -> Int): String {

        val result = ft(a, b) //OR ft.invoke(a, b)

        return doSomething:  + result
    }

There is one thing to remember here:.

A new function object will be created for each and every function type of a higher order function.

How to call/use/execute such a higher order function?

We know how to call a function but we may not know how to pass a function type argument/s in any higher order function!

We can pass function type arguments using function literal, lambda expression or by anonymous function. Let us check these all one by one.

Function literal

Signature / Syntax: 1

    { comma separated pascal parameters -> business logic }

Example:

    { x: Int, y: Int -> x + y }

Note that the last statement in a function literal is considered as a return statement. So, the last statement in a function literal decides the return type.

We can use function literal to pass as a function type argument for higher order function as below:

    //Calling a higher order function 

    println(doSomething(1, 2, {x: Int, y: Int -> x + y})) 

    //prints: doSomething: 3

OR if the function type parameter is the last parameter in the higher order function, we can write our function literal after the closing function parenthesis as below:

    //Calling a higher order function

    println(doSomething(1, 2){x: Int, y: Int -> x + y})

    //prints: doSomething: 3

OR if the higher order function has only one parameter or say if the function type parameter is one and only parameter in a higher order function like below:

   //region A higher order function that has one and only function type parameter
    private fun doSomething(ft: (Int, Int) -> Int) {
        val result = ft(1, 2)
        /*...*/
    }
   //endregion

While calling such a higher order function, we can omit the function call parentheses like below:

        doSomething { x: Int, y: Int -> x + y }

Syntax / Signature 2

Also, if the function type is only parameter in a higher order function and if the function type has also only one parameter like below:

 private fun doSomething(ft: (Int) -> String) {
        /*...*/
 }

While passing such a function literal, in addition to function call parentheses, we can also omit the parameter and an arrow -> ! We just write core business logic between curly braces and we can access our single parameter through the keyword it like below:

doSomething { "$it" }

And if the higher order function has only one function type parameter and the function type has no parameter like below:

private fun doSomethingY(ft: () -> String) {
        /*...*/
}

We can simply write our business logic between curly braces right after the higher order function name as below:

doSomethingY { "test" }

Types:

There are two types of function literals.

  1. Lambda expression

  2. Anonymous function

Lambda expression

Lambda expression is just another way to define a function in a short way.

Signature / Syntax 1

We can either specify explicit function type and let the data type of parameters inferred in below format:

nameOfTheLambda: (explicit function type) = { comma separated parameter: Inferred data type -> business logic }

Or we can give explicit type annotation to parameters and let the function type inferred like below format:

nameOfTheLambda: (inferred function type) = { comma separated parameter: Explicit dataType -> business logic}

Or we can write both function type and data type of parameter (but why?) like below:

nameOfTheLambda: (explicit function type) = { comma separated parameter: Explicit dataType -> business logic}

Let us see an example:

    /**
     * nameOfTheLambda: function type 
     * = { comma separated pascal parameters -> business logic }
     */

    val lambda: (Int, Int): Int = { x: Int, y: Int -> x + y }

Signature / Syntax 2 for special case

If a lambda has only one parameter, we can omit everything except a business logic inside the curly braces and we can access the single argument using the keyword: it

Example:

Suppose we have a lambda expression like below:

    val lambdaIncrement: (Int): Int = { x: Int -> x + 1 }

We can write the equivalent lambda as below:

    val lambdaIncrement: (Int): Int = { it + 1 }

Summary for a lambda expression having a single parameter

Usage: How to call / execute / use lambda expression

We can use above lambda expression directly like below:

    println(lambda(1,2)) //prints: 3

OR we can pass a lambda as a function type argument to a higher order function like below:

    println(doSomething(1, 2, lambda)) //prints: doSomething: 3

Sometimes, the common term “lambda” is used to represent a function type, function literal or a lambda expression.

Anonymous function

Signature / Syntax

    //fun(comma separated pascal parameters) = business logic

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

We can store an anonymous function in a variable like below:

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

Usage: How to use an anonymous function

We use an anonymous function as an argument for a higher order function like below:

    println(doSomething(1, 2, fun(x: Int, y: Int) = x + y )) 

    //prints: doSomething: 3

We can use an anonymous function through a variable to pass as an argument in a higher order function as below:

    println(doSomething(1, 2, anonymouseFunction) 

    //prints: doSomething: 3

That’s all! If you have read this article, if you find this article helpful, you can click on that heart icon 😉

Applauds and creative critics are always welcome 😇

In next article, we will learn about Extension function and Receiver type.

Thanks for reading the article! Have a great day 😇

Let us be Connected

https://www.linkedin.com/in/srdpatel

https://twitter.com/iSrdPatel

Tags: kotlin, function type, function literal, lambda expression, anonymous function, higher order function

💖 💪 🙅 🚩
srdpatel
Sagar

Posted on May 1, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related