Professional Documents
Culture Documents
Function References in Kotlin
Function References in Kotlin
Function references are another of those great improvements that we get with Kotlin, which are
kind of exotic when we come from Java.
You already know that Kotlin supports functions as a type, what means that you can save a
function in a variable, use it as another function argument, or even make that a function returns
another function.
This is the main feature to consider that a language supports functional programming style, and
Kotlin of course allows this. You can declare a function in a variable like this:
This is a function that receives two integers and returns one integer. In this particular
implementation, the lambda is applying an addition operation.
You could then have a function that accepts a lambda of this type as an argument:
fun applyOp(x: Int, y: Int, op: (Int, Int) -> Int): Int = op(x, y)
This is taking two integers and applying the function to both, so you can use the combination of
both this way:
applyOp(2, 3, sum)
This is doing the same, but instead of having a variable that keeps the function, we just have a
function. Now, if you look at the call above, it is failing:
applyOp(2, 3, sum)
We need to use the function reference. For that, you only have to prepend two colons to the name
of the function:
applyOp(2, 3, ::sum)
a function reference behaves as a lambda, and as such, you can assign this reference to a variable
with the same structure:
fun main () {
val funcMultiply = {a: Int, b: Int -> a*b}
println (funcMultiply (4, 3))
val funcSayHi = {name: String -> println ("Hi $name") }
funcSayHi("John")
}
So now that we have a general idea of how lambdas work, let’s try and pass one in another
function-that is, we will try a high-order function.
fun main () {
val funcMultiply : (Int, Int) ->Int = {a: Int, b:Int -> a*b}
val funcSum : (Int, Int) ->Int = {a: Int, b: Int -> a+b}
performMath (3, 4, funcMultiply)
performMath (3, 4, funcSum)
}
fun performMath (a: Int, b:Int, mathFunc : (Int, Int) -> Int) : Unit
{
println ("Value of calculation: ${mathFunc (a, b) }")
}
It is as simple as that-create a function lambda and pass it into the function. So this is just one aspect of
a high-order function-that is, we can pass a function as an argument to the function. Another use of
high-order functions is to return a function. Consider the following example where we need a function
that transforms the total price of an order according to certain conditions. Kind of like an e-commerce
site, but way simpler.
fun main() {
// free delivery of order above 499
val productPricel = 600;
// not eligible for free delivery
val productPrice2 = 300;
val totalCost1 = totalCost (productPrice1)
val totalCost2 = totalCost (productPrice2)
println("Total cost for item 1 is ${totalCost1 (productPrice1) }")
println ("Total cost for item 2 is ${totalCost2 (productPrice2) }")
}
Note how we need to change functions that we apply based on certain conditions so that we
return a function that suits the conditions. We assign the returned function to a variable and then
we can just put append () in front of the variable to use it as a function, just like we did with the
lambdas. This works because the high-order function is essentially returning a lambda.
In Kotlin, we can assign a function to a variable, and then we can pass it into a function or return
it from a function. This is because it’s essentially declared like a variable. This is done using a
lambda declaration of functions.
// function declaration
fun mul(a: Int, b: Int): Int{
return a*b
}
//higher-order function declaration
fun higherfunc() : ((Int,Int)-> Int){
return ::mul
}
fun main() {
// invoke function and store the returned function into a variable
val multiply = higherfunc()
// invokes the mul() function by passing arguments
val result = multiply(2,4)
println("The multiplication of two numbers is: $result")
}
generic type. A variable number of arguments (also known as varargs) is a feature of the Kotlin
language that allows you to pass a number of values as a single argument variable to a function.
When defining a function, you usually need to specify the name of each parameter that the function can
receive inside the function parentheses.
sumNumbers(2, 3) // 5
Now when you want to sum more numbers, you need to add another parameter to the function
definition.
sumNumbers(2, 3, 4)
One way of solving this problem might be to convert the numbers into an array.
That way, you can pass a single parameter of an IntArray type to the function and call the
sum() function rather than passing them one by one.
sumNumbers(numArray) // 1+2+3+4 = 10
A varargs is similar to how an array works. It allows you to pass a single variable that contains
multiple values. But when using a vararg, you don’t need to create an array. You can pass your
values separated by a comma, just like normal arguments.
To define a variable of arguments, you need to add the vararg keyword before the parameter
name as shown below:
sumNumbers(1, 2, 3, 4, 5) // 15
Notice how the vararg keyword is added before the numbers parameter and the values to sum
are passed just like regular arguments during the sumNumbers() call. This is the power of
varargs in Kotlin. It allows you to define a single variable as a function parameter that can
accept more than one value.
A vararg argument will be available inside the function as if it was an Array type data.
In the example above, you can call the same sum() function that’s available for IntArray type.
We can even pass all the elements of an array along with other arguments to a vararg variable. We can
use the spread (*) operator to do the same.