Skip to content

Beginner: Kotlin · Null safety, functions and lambdas · topic 7 of 50 · 30 min

Lambdas and higher-order functions

Explanation

A lambda is a small function without a name, written in braces: { a: Int, b: Int -> a + b }. Functions are values in Kotlin, with types like (Int) -> Int. A higher-order function takes or returns a function. When a lambda has one parameter, you can call it it, and when it is the last argument it goes outside the parentheses: this trailing-lambda syntax is why Compose code looks the way it does.

Functions as values

In Kotlin you can store a function in a variable, pass it to another function, and return it from a function, just like a number or a string. This lets you pass behaviour around: "sort by price", "keep only paid orders", "run this when the button is clicked".

Lambda syntax

kotlin
val add = { a: Int, b: Int -> a + b }
println(add(3, 4))           // 7

val shout: (String) -> String = { text -> text.uppercase() + "!" }
println(shout("jai hind"))   // JAI HIND!
Parameters come before the arrow ->, the body after it. The last expression is the result.

The type (String) -> String reads "a function that takes a String and returns a String". () -> Unit is a function that takes nothing and returns nothing, like a click handler.

Why does this matter for Android? Almost every Android API that reacts to something takes a function: what to do when a button is clicked, when a network call finishes, when a list item is swiped. Instead of writing a whole class for each reaction (the old Java way), you pass a short lambda right where it is used, so the reaction sits next to the code it belongs to.

it: the implicit parameter

kotlin
val double: (Int) -> Int = { it * 2 }
println(double(21))          // 42
If a lambda has exactly one parameter, you may leave it out and refer to it as it.

Higher-order functions

A higher-order function is a function that takes another function as a parameter or returns one. The collection functions you will use daily (filter, map, sortedBy, forEach) are all higher-order functions.

kotlin
fun applyDiscount(price: Int, rule: (Int) -> Int): Int = rule(price)

fun main() {
    val festive = { p: Int -> p - p / 10 }        // 10% off
    println(applyDiscount(500, festive))          // 450
    println(applyDiscount(500) { it - 50 })       // 450: trailing lambda
}
The rule is passed in, so the same function supports any discount.

Trailing lambda syntax

If the last parameter of a function is a function, you can write the lambda after the closing parenthesis. If it is the only argument, you can drop the parentheses completely. This is used everywhere in Kotlin and Android:

kotlin
val prices = listOf(120, 45, 300)
val big = prices.filter { it > 100 }        // [120, 300]
repeat(2) { println("Hi") }

// Jetpack Compose (module 6) uses the same idea:
// Button(onClick = { count++ }) { Text("Add") }
// Column { Text("Name"); Text("City") }
Now Compose code will look familiar: those braces are trailing lambdas.

Function references

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

val evens = listOf(1, 2, 3, 4).filter(::isEven)   // [2, 4]
::isEven passes an existing named function where a lambda is expected.

Lambdas capture variables

kotlin
var clicks = 0
val onClick = { clicks++ }
onClick()
onClick()
println(clicks)    // 2
A lambda can read and change variables from where it was created (a closure).
Think of it like this: A lambda is like a sticky note with an instruction that you hand to someone else: "add 10% GST", "only keep paid bills". The person (the higher-order function) does the repetitive work and applies your instruction to every item.

Common mistakes

  • Using return inside a lambda passed to forEach and expecting it to skip one item: a plain return returns from the enclosing function. Use return@forEach or filter first.
  • Forgetting that the last expression in a lambda is its result. Do not write return there.
  • Overly long lambdas. If it is more than a few lines, make it a named function and pass ::name.
  • Confusing it in nested lambdas. Give parameters names when lambdas are nested.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Lambdas and higher-order functions · 1/6

Functions = values

In Kotlin, functions are values. You can store them, pass them and return them.

Prefer a video by a teacher? Find free videos on “kotlin lambdas higher order functions trailing lambda it” on YouTube ↗

In real life: Sorting restaurant search results

A food delivery app lets users sort restaurants by rating, distance or delivery time. Instead of three separate sort functions, the screen keeps the current sort rule as a function value of type (Restaurant) -> Double and passes it to sortedBy. Adding "sort by price" means adding one more lambda.

kotlin
data class Restaurant(val name: String, val rating: Double, val km: Double)

fun main() {
    val list = listOf(Restaurant("Annapurna", 4.4, 2.5), Restaurant("Spice Hub", 4.7, 5.0))
    val byDistance: (Restaurant) -> Double = { it.km }
    val byRating: (Restaurant) -> Double = { -it.rating }   // highest first
    println(list.sortedBy(byDistance).map { it.name })      // [Annapurna, Spice Hub]
    println(list.sortedBy(byRating).map { it.name })        // [Spice Hub, Annapurna]
}
data class is covered in module 3; here it is just a small record.

Practice (0/3 done)

Task 1 · Question

What does this print? val f: (Int) -> Int = { it * it + 1 } println(f(3))

Task 2 · Question

Which type describes a click handler that takes nothing and returns nothing?

Task 3 · Practice

Write fun applyAll(prices: List<Int>, rule: (Int) -> Int): List<Int> that applies the rule to each price (use a loop or map). Call it with three lambdas: add 18% GST, subtract a flat Rs 50 (not below 0), and round to the nearest 10. Use trailing lambda syntax at least once.

Quick quiz

Question 1

1.What is a higher-order function?

Question 2

2.In { it > 5 }, what is it?

Question 3

3.What is the result of a lambda?

Question 4

4.Which call uses trailing lambda syntax?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is a higher-order function?

Answer: A function that takes or returns another function

filter and map are higher-order functions.

In { it > 5 }, what is it?

Answer: The implicit name of the single parameter

it is used when a lambda has one parameter.

What is the result of a lambda?

Answer: The value of its last expression

The last expression is returned automatically.

Which call uses trailing lambda syntax?

Answer: list.filter { it > 0 }

The lambda moves outside the parentheses.

What makes a lambda "generic"?Related

Answer: It uses auto in its parameter list

auto parameters turn the call operator into a template.

From Lambdas: small functions written in place

In Func<string, int>, what is the return type?Related

Answer: int

The last type parameter of Func is the return type.

From Delegates, lambdas, Func, Action and Predicate

When did lambdas arrive in Java?Related

Answer: Java 8

Java 8 (2014) added lambdas and streams.

From Lambdas and functional interfaces

Which is a higher-order function?Related

Answer: A function that takes another function as an argument

Higher-order functions take or return functions.

From Higher-order functions and recursion

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Null safety, functions and lambdas” before its exam: Extension functions and scope functions.
  2. Module 2 exam: Null safety, functions and lambdas · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Classes, objects and collections. 50 topics left in the course before the final exam.

← Previous: Functions