Skip to end of metadata
Go to start of metadata

A function literal as an "anonymous function", i.e. a function that is not declared, but passed immediately as an expression. Consider the following example:

max(strings, {a, b -> a.length < b.length})

Function max is a higher-order function, i.e. is takes a function value as the second argument. This second argument is an expression that is itself a function, i.e. a function literal. As a function, it is equivalent to

fun compare(a : String, b : String) : Boolean = a.length < b.length

Function types

For a function to accept another function as a parameter, we have to specify a function type for that parameter. For example the abovementioned function max is defined as follows:

fun max<T>(collection : Collection<out T>, less : (T, T) -> Boolean) : T? { 
  var max : T? = null 
  for (it in collection) 
    if (max == null || less(max, it)) 
      max = it 
  return max 
}

The parameter less is of type (T, T) -> Boolean, i.e. a function that takes two parameters of type T and returns a Boolean: true if the first one is smaller than the second one.

In the body, line 4, less is used as a function: it is called by passing two arguments of type T.

A function type is written as above, or may have named parameters, for documentation purposes and to enable calls with named arguments.

val compare : (x : T, y : T) -> Int = ...

Syntactic forms of function literals

The full syntactic form of function literals, i.e. literals of function types, is as follows:

val sum = {(x : Int, y : Int) : Int -> x + y}
  • A function literal is always surrounded by curly braces,
  • parameter declarations in the full syntactic form go inside parentheses and have optional type annotations,
  • the optional return type annotation goes after the parameter list,
  • the body goes after an '->' sign.

If we leave all the optional annotations out, what's left looks like this:

val sum : (Int, Int) -> Int = {(x, y) -> x + y}

As this is the most common case, Kotlin allows us to leave the parentheses out as well, if no type annotations are present, and so we get the short syntactic form for functional literals:

val sum : (Int, Int) -> Int = {x, y -> x + y}

It very common that a function literal has only one parameter. If Kotlin can figure the signature out itself, it allows us not to declare the only parameter, and will implicitly declare it for us under the name it:

ints.filter {it > 0} // this literal is of type '(it : Int) -> Boolean'

Note that if a function takes another function as the last parameter, the function literal argument can be passed outside the parenthesized argument list. See Higher-order functions and the grammar for callSuffix.

See the grammar for function literals here.

Closures

A function literal (as well as a local function and object expressions) can access its closure, i.e. the variables declared in the outer scope. Unlike Java the closure variables can be modified:

var sum = 0 
ints filter {it > 0} forEach { 
  sum += it 
} 
print(sum)

Extension function literals

Besides ordinary functions, Kotlin supports extension functions. This kind of functions in so useful, that extension function literals are also supported. One of the most important examples of their usage is Type-safe Groovy-style builders.

An extension function differs from an ordinary one in that it has a receiver type specification. One can specify a receiver type in a function literal as well:

val sum = {Int.(other : Int) : Int -> this + other}

Receiver type may be specified only in the full syntactic form of a function literal (remember that parameter types and return type annotations are optional in this form).

Such a literal has a function type with receiver:

sum : Int.(other : Int) -> Int

it can be called with a dot or in infix form (since it has only one parameter):

1.sum(2) 
1 sum 2

Disambiguation of this expressions

See This expressions.

What's next

Expressions

Functions

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jul 24, 2011

    Anonymous

    Just curious, what do you call the '=>' sign in Kotlin?

    Thanks.

    --

    1. Jul 25, 2011

      Fat arrow

  2. Jan 25, 2012

    I'm not sure if this is the right place to ask, but how do I get the following example to compile? I want to assign one of my functions to a variable (or value)

    1. Jan 25, 2012

      Currently, the only way to do this is to say:

      fun doub(i: Int): Int { return i * 2; } 
       
      fun main(args : Array<String>) { 
        val t2 = {(i : Int) -> doub(i)} 
      }
      1. Dec 19, 2012

        Are there any thoughts or plans about implementing the ability to pass non-literal functions (or even methods) as arguments? That would be a huge feature and really let you write clean, composable code.

        1. Dec 19, 2012

          Yes, we will support this. Hopefully, rather soon.

  3. Nov 19, 2012

    Reading about the outer scope in the section about closures brought the idea of inner in Beta to my mind: see Fig.2 on p.6 in this document. I liked that idea and it has gone completely lost. Do you think inner would be useful for Kotlin? I know it conflicts somehow with super, but it might be worth considering :-).

    1. Nov 19, 2012

      What use cases do you have in mind?

      1. Nov 20, 2012

        Oh yeah, I should have expected this answer ... ;-). Lazy as I am I just cloned the example from the document:

        This is not really in the spirit of inner as in Beta, but Beta is the only language I have seen where MySubClass.first() would automatically call super.first() without the developer having coded this explicitly.

        I tried to play around with the Qualified this thing. But I guess it does not apply here, since traits and classes are not nestedt in the way of nested classes. The problem with this example is IMHO that the trait with inner.first() takes over control of what is happening. But control should always remain with the class using the trait. At least that's the way I used to see things.

        Nevertheless, maybe there is still a point with inner here as it saves some extra methods.

        1. Nov 20, 2012

          Well, I believe it does not work. You just do this:

          The inner.first() thing only saves us from having to declare

          and that is not too much of a bang to justify a new keyword, I believe. Maybe someone else or me still gets a good idea how to use it ;-).

          1. Nov 20, 2012

            Agree