Step 1 of 5 · Reading · ~4 min
Learn
Functions and Lambdas
Lambdas and Higher-Order Functions
A lambda is a function with no name, written between braces, that you can store in a variable and hand to other functions.
fun main() {
val double: (Int) -> Int = { n -> n * 2 }
val join: (String, String) -> String = { a, b -> a + " " + b }
println(double(5))
println(join("ship", "code"))
}
//> 10
//> ship code
There are two halves to read here. (Int) -> Int is a type — "takes an Int, gives back an
Int" — and { n -> n * 2 } is a value of that type. Parameters go to the left of the arrow,
the body to the right.
No return inside a lambda
A lambda's result is simply its last expression. No return keyword is involved.
✓ Correct — the last line is the result:
val classify: (Int) -> String = { n ->
val sign = if (n < 0) "neg" else "pos"
sign
}
✗ Wrong — return inside a lambda tries to return from the enclosing function, which here is
a compile error and in general is never what a beginner means:
val classify: (Int) -> String = { n -> return if (n < 0) "neg" else "pos" }
it: the name you get for free
When a lambda takes exactly one parameter you may skip naming it. Kotlin calls it it.
fun main() {
val nums = listOf(1, 2, 3, 4)
println(nums.map { it * 2 })
println(nums.filter { it % 2 == 0 })
}
//> [2, 4, 6, 8]
//> [2, 4]
Note how the list is built: listOf(1, 2, 3, 4). Kotlin has no [1, 2, 3] literal syntax, so
square brackets there would not compile. Use it for short one-liners and give the parameter a
real name the moment the lambda grows past one line or sits inside another lambda.
Higher-order functions
A function that accepts or returns another function is called higher-order. Declare the parameter with a function type, then call it like anything else.
fun applyTwice(n: Int, op: (Int) -> Int): Int {
return op(op(n))
}
fun main() {
println(applyTwice(3) { it + 1 })
println(applyTwice(3) { it * it })
}
//> 5
//> 81
Follow the second one through: the inner op(3) gives 9, and the outer op(9) gives 81.
applyTwice never knows what op does — that is exactly the point.
The trailing-lambda rule
If the last parameter is a function, the lambda may move outside the parentheses. If it is the only argument, the parentheses vanish entirely.
| Written as | Legal | Idiomatic |
|---|---|---|
applyTwice(3, { it * it }) | yes | no |
applyTwice(3) { it * it } | yes | yes |
nums.map({ it * 2 }) | yes | no |
nums.map { it * 2 } | yes | yes |
That single rule is why nums.map { it * 2 } reads like built-in syntax when it is really an
ordinary function call. The whole standard library — map, filter, forEach, sortedBy,
fold — is built on it.
fun main() {
println(listOf(1, 2, 3, 4).fold(0) { acc, n -> acc + n })
}
//> 10
fold starts from 0 and folds each element in with your lambda: 0 + 1, then 1 + 2, then
3 + 3, then 6 + 4.
Your exercise
Apply Twice asks you to finish applyTwice(n, op) so it applies op to n and then
applies op to that result. The main you are given calls it with a squaring lambda, so the
printed answer is N to the fourth power.
Two mistakes the grader catches. First, the starter's body is return 0; leave it sitting below
your own line and every test prints 0, because the first return reached wins. Second,
applying op only once — return op(n) — prints 4 for the visible test that feeds 2 and
expects 16. The calls have to nest: the result of the inner call is the argument to the outer
one.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…