DEV Community

Sagar
Sagar

Posted on • Edited on

2 1

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
//Name: (only comma separated data types) -> return data type
ft: (Int, Int) -> Int
view raw functionType.kt hosted with ❤ by GitHub

How to call / execute a function type?

    ft(1, 2) 

    //OR

    ft.invoke(1, 2)
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
        }

    }
//We can implement a function type like an interface
class ClassName : (Int, Int) -> Int {
/**
* 4/24/2020
* Override method when we implement a function type
* <p>
* Like an interface, we can implement a function type too.
* When we implement a function type, we get a method called "invoke" to override having a similar signature of the
* implemented function type
* </p>
* @author srdpatel
* @since 1.0
*/
override fun invoke(p1: Int, p2:Int): Int {
return p1 + p2
}
}
view raw functionType.kt hosted with ❤ by GitHub

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
    }
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 }
//Syntax of a function literal: { comma separated pascal parameters -> business logic }
{ 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
//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
//Passing function literal after the function parenthesis when the last argument is function type
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
//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
view raw hOfOneFt.kt hosted with ❤ by GitHub

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

        doSomething { x: Int, y: Int -> x + y }
/**
* While calling the higher order function When the function type parameter is only parameter,
* we can simply write our business logic between curly braces after writing the function name
* and omit 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) {
        /*...*/
 }
//region A function type that has only one parameter
private fun doSomething(ft: (Int) -> String) {
/*...*/
}
//endregion

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" }
/**
* While calling the higher order function When the function type parameter is one and only parameter,
* and if the function type has also one and only parameter,
* in addition to function call parentheses, we can also omit the parameter of the function type 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" }
view raw flOneParam.kt hosted with ❤ by GitHub

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) {
        /*...*/
}
//region A function type that has no parameter
private fun doSomethingY(ft: () -> String) {
/*...*/
}
//endregion

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

doSomethingY { "test" }
/**
* 5/8/2020
* A function type without any parameter
* <p>
* if the higher order function has only one function type parameter and the function type has no parameter,
* We can simply write our business logic between curly parentheses right after the name of the function.
* </p>
* @author srdpatel
* @since 1.0
*/
doSomethingY { "test" }
view raw callFt.kt hosted with ❤ by GitHub

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 }
//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 }
val lambdaIncrement: (Int): Int = { x: Int -> x + 1 }

We can write the equivalent lambda as below:

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

Summary for a lambda expression having a single parameter

//Normal function
fun increment (x: Int): Int {
return x + 1
}
//The equivalent lambda expression for above function
val lambda: (Int): Int = { x -> x + 1 }
//The equivalent short lambda expression for above single parameter lambda
val lambda: (Int): Int = { it + 1 }

Usage: How to call / execute / use lambda expression

We can use above lambda expression directly like below:

    println(lambda(1,2)) //prints: 3
println(lambda(1,2)) //prints: 3
view raw callLambda.kt hosted with ❤ by GitHub

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
println(doSomething(1, 2, lambda)) //prints: doSomething: 3
view raw passLambda.kt hosted with ❤ by GitHub

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
//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
//Storing an anonymous function in a variable
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
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
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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay