Skip to main content
A lambda expression in Kotlin is an anonymous function literal defined within curly braces {} that can be treated as a first-class value. It is not declared with the fun keyword, but rather instantiated as an object of a function type, allowing it to be assigned to variables, passed as an argument, or returned from higher-order functions.

Base Syntax

The full syntactic form of a lambda expression requires the parameters and the body to be enclosed within curly braces, separated by the -> operator.
val sum: (Int, Int) -> Int = { a: Int, b: Int -> a + b }
  • (Int, Int) -> Int: The explicit function type declaration.
  • { ... }: The lambda literal.
  • a: Int, b: Int: The parameter list.
  • ->: The arrow operator separating parameters from the body.
  • a + b: The lambda body.

Type Inference

The Kotlin compiler can infer parameter types and return types based on the context. If the function type is explicitly declared on the variable, the parameter types inside the lambda literal can be omitted.
val sum: (Int, Int) -> Int = { a, b -> a + b }

Implicit it Parameter

When a lambda expression has exactly one parameter, the compiler allows the omission of the parameter declaration and the -> operator. The single parameter is implicitly exposed under the name it.
val square: (Int) -> Int = { it * it }

Return Values

Lambda expressions do not use the return keyword for standard execution flow. The evaluated result of the last expression inside the lambda body is implicitly treated as the return value.
val calculateAndFormat: (Int, Int) -> String = { a, b ->
    val result = a + b
    "The result is $result" // Implicitly returned
}
To explicitly return from a lambda, a qualified return syntax (return@label) must be used, typically referencing the function to which the lambda was passed.

Trailing Lambda Convention

If the last parameter of a function is a function type, a lambda expression passed as the corresponding argument can be placed outside the function’s parentheses.
// Function signature: fun executeOperation(x: Int, operation: (Int) -> Unit)
executeOperation(10) { value ->
    println(value)
}
If the lambda is the only argument being passed to the function, the parentheses can be omitted entirely.
// Function signature: fun executeOperation(operation: () -> Unit)
executeOperation {
    println("Executing")
}

Unused Parameters

If a lambda has multiple parameters but not all are used within the body, the unused parameters can be replaced with an underscore _ to avoid compiler warnings and signal intent.
val processMap: (Int, String) -> String = { _, value ->
    "Processing $value"
}

Closures

Kotlin lambdas support closures, meaning they can access and modify variables declared in the outer scope where the lambda is defined. Unlike Java, Kotlin allows the mutation of captured variables (they do not need to be final or effectively final).
var counter = 0
val increment: () -> Unit = {
    counter++ // Mutating a variable from the enclosing scope
}

Destructuring in Lambdas

If a lambda parameter is a type that supports destructuring declarations (such as Pair, Map.Entry, or a data class), it can be destructured directly in the parameter list by wrapping the variables in parentheses.
val processPair: (Pair<Int, String>) -> Unit = { (id, name) ->
    println("$id: $name")
}
Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More