SkillByAIOpen interactive version →

Lesson 10 / 25

Lambdas and Higher-Order Functions

Function types, trailing lambdas and it.

Passing behaviour around

A higher-order function takes a function as a parameter or returns one. Function types are written like (Int, Int) -> Int, and nullable as ((String) -> Unit)?. A lambda is written in braces: { a, b -> a + b }; a single parameter can be referred to as it. If the last parameter is a function, the lambda can go outside the parentheses (trailing lambda syntax). Function references such as ::isValid or String::length pass existing functions. Marking a higher-order function inline removes lambda allocation overhead and allows return from the enclosing function inside the lambda.

Functions as values

Lambdas, a rich collections API and extension functions make Kotlin code declarative and readable.

Figure 4.1 — A collection flowing through filter, map and fold.

A retry helper taking a lambda

Trailing lambda syntax.

fun <T> retry(times: Int = 3, block: () -> T): T {
    var lastError: Exception? = null
    repeat(times) {
        try {
            return block()
        } catch (e: Exception) {
            lastError = e
        }
    }
    throw IllegalStateException("failed after $times attempts", lastError)
}

fun isEven(n: Int) = n % 2 == 0

fun main() {
    val sum: (Int, Int) -> Int = { a, b -> a + b }
    val evens = listOf(1, 2, 3, 4).filter(::isEven)       // function reference
    val lengths = listOf("a", "bb").map { it.length }     // it = single parameter
    val value = retry(times = 2) { sum(1, 2) }            // trailing lambda
}

A recipe with a blank step

A higher-order function is a recipe with one step left open, such as "season to taste"; the lambda you pass fills in that step.

Quick check: What does `it` refer to in `list.map { it * 2 }`?

  • The single parameter of the lambda, each element in turn
  • The list itself
  • The index of the element
  • The result of the previous call
Answer

The single parameter of the lambda, each element in turn — it is the implicit name of a single lambda parameter.