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 |
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 | |
} | |
} |
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 |
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" } |
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" } |
Types:
There are two types of function literals.
Lambda expression
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 |
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 |
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
Tags: kotlin, function type, function literal, lambda expression, anonymous function, higher order function
Top comments (0)