Another important feature of Kotlin functions is the ability to pass functions as arguments to other functions. This is partially what makes up the term higher-order functions, the other component being the ability to return functions from other functions.
A function argument can be added to a function the same way as any other argument type:
class GreetingViewModel {
private val greetings = listOf("Hey", "Hi", "What's up?")
fun printGreetings(filter: (String) -> Boolean) {
greetings
.filter(filter)
.forEach { greeting ->
println(greeting)
}
}
}
In this example, we've added a printGreetings function to print out all the available greetings. The function takes a function parameter with a signature that takes a String argument and returns Boolean. This function can then be used to filter the available greetings.
The following snippet shows the forEach function from the Kotlin standard library:
/**
* Performs the given [action] on each element.
*/
@kotlin.internal.HidesMembers
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
This forEach implementation is an extension function on the Iterable type, and it takes a generic action function as an argument. This action argument allows the caller to define the code to be run when each iterable element is visited.
Function arguments enable you to make use of the strategy pattern and encapsulate customizable logic into functions that can be passed around and replaced as needed. This can make code much more flexible, and is used heavily within the Kotlin standard library.