Consider 2 types X and Y , and a function f defined as:

class X class Y val f = { _ : X -> Y () } (1)

1 With Kotlin 1.3, it’s possible to name an unused parameter _ , to explicitly tell it’s ignored

The following snippet declares a function similar to f . Then, it executes it with a parameter of type X using the invoke() function:

fun f ( x : X ) = Y () val y : Y = f . invoke ( X ())

The Java equivalent would be Function.apply() :

interface Function < T , R > { R apply ( T t ); }

In Kotlin, it’s also possible to call the function using an equivalent syntax:

val y : Y = f ( X ())

This alternative syntax is possible because invoke() is an operator. Operators are a limited group of functions that offer a specific alternative syntax.

Languages such as C and Scala allow functions to be named how one wants e.g. + , ! , ::= or perhaps even 🤔. Experience from using such languages has shown that the flip side of this freedom is a boom of symbol functions, that often result in (very) hard-to-read code. On the opposite side of the spectrum, Java completely disallows special characters in method names in order to avoid that problem. While sometimes the target of jokes, long method names allow unfamiliar readers to understand what the method does. Other languages have chosen a middle path, such as Groovy:

Groovy allows you to overload the various operators so that they can be used with your own classes. All (non-comparator) Groovy operators have a corresponding method that you can implement in your own classes. — Groovy documentation

http://groovy-lang.org/operators.html#Operator-Overloading

Kotlin follows the same approach: there is a limited number of operator functions that offer an alternative syntax. invoke() is one of them. Here’s the list of such available alternatives:

Expression Translated to a() a.invoke() a(i) a.invoke(i) a(i, j) a.invoke(i, j) a(i_1, ..., i_n) a.invoke(i_1, ..., i_n)

This allows to write interesting constructs:

data class Point ( var x : Int , var y : Int ) class Translate ( val x : Int , val y : Int ) { operator fun invoke ( point : Point ) = Point ( point . x + x , point . y + y ) (1) } val point = Point ( 1 , 1 ) val translate = Translate ( 5 , 10 ) (2) val translated = translate ( point ) (3)

1 Declare a new operator function - invoke() 2 Create a new instance of Translate 3 This is equivalent to translate.invoke(point) , though it looks like a top-level function call