Chapter 9 of 12
~18 min read
Lambdas & Higher-Order Functions
Kotlin's lambda syntax is more concise than Java. Learn the 5 scope functions and how to write your own higher-order functions.
Lambda Syntax
Java 8+ Lambdas
// Verbose functional interface
Runnable r = () -> System.out.println("Hi");
// With parameters
Comparator<String> comp =
(a, b) -> a.compareTo(b);
// In stream:
list.stream()
.filter(s -> s.length() > 3)
.forEach(s -> System.out.println(s)); Kotlin Lambdas
// Lambda syntax: { params -> body }
val printHi = { println("Hi") }
// With parameters:
val compare = { a: String, b: String ->
a.compareTo(b)
}
// 'it' shorthand for single parameter:
list.filter { it.length > 3 }
.forEach { println(it) }Higher-Order Functions
Functions that accept or return other functions. You've been using them with filter, map, etc.:
Kotlin
// Accept a function as parameter
fun transform(value: Int, action: (Int) -> String): String {
return action(value)
}
// Call with a lambda:
val result = transform(42) { "Value is $it" }
// "Value is 42"
// Return a function:
fun multiplier(factor: Int): (Int) -> Int {
return { number -> number * factor }
}
val triple = multiplier(3)
triple(5) // 15The 5 Scope Functions
Kotlin's scope functions are the most Kotlin-idiomatic code patterns. They replace repetitive assignments and null checks:
| Function | Context object | Returns | Best for |
|---|---|---|---|
let | it | Lambda result | Null checks, transformations |
apply | this | Context object | Object initialization / builder pattern |
run | this | Lambda result | Initialization + computation |
also | it | Context object | Side effects (logging, assertions) |
with | this | Lambda result | Group operations on an object |
Kotlin — scope function examples
// let — transform or null-safe operation
val name: String? = " Alice "
val length = name?.let { it.trim().length } // 5
// apply — configure an object, returns the object
val intent = Intent(context, MainActivity::class.java).apply {
putExtra("KEY", "value")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
// run — execute block and return result
val result = "Hello".run {
lowercase() + " world"
} // "hello world"
// also — side effect, returns original object
val user = User("Alice", 30)
.also { println("Created: ${it.name}") }
// user is still User("Alice", 30)
// with — group operations
val sb = StringBuilder()
with(sb) {
append("Hello")
append(", ")
append("World!")
}
println(sb) // Hello, World!