Beginner: Kotlin · Null safety, functions and lambdas · topic 7 of 50 · 30 min
Lambdas and higher-order functions
Explanation
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
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!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
val double: (Int) -> Int = { it * 2 }
println(double(21)) // 42Higher-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.
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
}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:
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") }Function references
fun isEven(n: Int) = n % 2 == 0
val evens = listOf(1, 2, 3, 4).filter(::isEven) // [2, 4]Lambdas capture variables
var clicks = 0
val onClick = { clicks++ }
onClick()
onClick()
println(clicks) // 2Common 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
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.
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]
}Practice (0/3 done)
What does this print? val f: (Int) -> Int = { it * it + 1 } println(f(3))
Which type describes a click handler that takes nothing and returns nothing?
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
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Extension functions and scope functionsNull safety, functions and lambdas · same module
- Null safetyNull safety, functions and lambdas · same module
- Lambdas: small functions written in placeC++ Programming (modern C++ and DSA) · Modern C++: lambdas, C++17 and C++20 essentials
- Delegates, lambdas, Func, Action and PredicateC# and .NET · Exceptions, delegates, events and async
- Lambdas and functional interfacesJava Programming (Core to Spring Boot) · Lambdas, streams and files
- Higher-order functions and recursionJavaScript Programming (language in depth) · Functions and closures
Questions people ask about this
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.
In Func<string, int>, what is the return type?Related
Answer: int
The last type parameter of Func is the return type.
When did lambdas arrive in Java?Related
Which is a higher-order function?Related
Answer: A function that takes another function as an argument
Higher-order functions take or return functions.
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 more topic in “Null safety, functions and lambdas” before its exam: Extension functions and scope functions.
- Module 2 exam: Null safety, functions and lambdas · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Classes, objects and collections. 50 topics left in the course before the final exam.