Back in Chapter 2, Getting Started with Functional Programming, in the section First-class and high-order functions, when we introduced lambda functions, we show the definition of Function1:
/** A function that takes 1 argument. */
public interface Function1<in P1, out R> : Function<R> {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
The invoke function is an operator, a curious one. The invoke operator can be called without name.
The class Wolf has an invoke operator:
enum class WolfActions {
SLEEP, WALK, BITE
}
class Wolf(val name:String) {
operator fun invoke(action: WolfActions) = when (action) {
WolfActions.SLEEP -> "$name is sleeping"
WolfActions.WALK -> "$name is walking"
WolfActions.BITE -> "$name is biting"
}
}
fun main(args: Array<String>) {
val talbot = Wolf("Talbot")
talbot(WolfActions.SLEEP) // talbot.invoke(WolfActions.SLEEP)
}
That's why we can call a lambda function directly with parenthesis; we are, indeed, calling the invoke operator.
The following table will show you different declarations of invoke with a number of different arguments:
Operator | Equivalent | Notes |
x() | x.invoke() | |
x(y) | x.invoke(y) | |
x(y1, y2) | x.invoke(y1, y2) | |
x(y1, y2..., yN) | x.invoke(y1, y2..., yN) |