Kotlin with copilot: Use lambda function to print out a name
Video: Kotlin with copilot: Use lambda function to print out a name by Taught by Celeste AI - AI Coding Coach
Kotlin: Lambda to Print a Name
val printName: (String) -> Unit = { name -> println("Name: $name") }. The single-parameter version of episode 26 — the simplest possible lambda.
A small step from the two-arg version. One parameter, one side effect.
The Copilot prompt
fun main() {
// Lambda that takes a name and prints it
val printName: (String) -> Unit =
Copilot generates:
val printName: (String) -> Unit = { name ->
println("Name: $name")
}
printName("Alice") // Name: Alice
Implicit it for single-parameter lambdas
For lambdas with exactly one parameter, you can omit the parameter name and use it:
val printName: (String) -> Unit = { println("Name: $it") }
it is the implicit name of the single parameter. Reads cleanly:
listOf(1, 2, 3).forEach { println(it) }
listOf("a", "b", "c").map { it.uppercase() }
forEach and map take single-arg lambdas; it is their parameter.
For multi-parameter lambdas ({ x, y -> ... }), there's no it — explicit names required.
When to name the parameter
it is fine for short lambdas. For longer or nested code, name explicitly:
// Clear:
val printName: (String) -> Unit = { name -> println("Name: $name") }
// Less clear with nesting:
list.map { item ->
item.children.map { child ->
"${item.name} -> ${child.name}"
}
}
// Confusing — which `it` is which?
list.map { it.children.map { ... } }
Rule of thumb: explicit name when nested or when it doesn't read naturally.
forEach: the canonical use
forEach takes a (T) -> Unit lambda — apply a side-effecting function to each element:
val names = listOf("Alice", "Bob", "Charlie")
names.forEach { println("Hello, $it!") }
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!
forEach is for side effects — print, write, send to API. For transformations, use map. For filtering, use filter. Each tool has a purpose.
forEachIndexed: with the index
names.forEachIndexed { index, name ->
println("$index: $name")
}
// 0: Alice
// 1: Bob
// 2: Charlie
When you need both the position and the value. Note the lambda has two parameters now, so it doesn't apply.
Lambdas as arguments
fun greet(name: String, formatter: (String) -> String) {
println(formatter(name))
}
greet("Alice", { name -> "Hello, $name!" })
// Or with trailing-lambda syntax:
greet("Alice") { name -> "Hello, $name!" }
// Or with implicit it:
greet("Alice") { "Hello, $it!" }
Three increasingly idiomatic forms of the same call.
Why store a lambda in a variable?
For one-off use, a regular function is fine. For:
- Conditional behaviour. Pick the function at runtime based on user choice.
- Closures. Capture state at creation time:
fun makeGreeter(greeting: String): (String) -> String {
return { name -> "$greeting, $name!" }
}
val hi = makeGreeter("Hi")
val hello = makeGreeter("Hello")
println(hi("Alice")) // "Hi, Alice!"
println(hello("Bob")) // "Hello, Bob!"
Each makeGreeter call returns a new function with its own captured greeting.
- Passing to async code. Callbacks, event handlers.
Lambda vs anonymous function
Kotlin has two anonymous-function syntaxes:
// Lambda
val printName1: (String) -> Unit = { name -> println(name) }
// Anonymous function (more verbose, more flexible)
val printName2 = fun(name: String): Unit { println(name) }
The lambda is shorter. The anonymous-function form lets you return early without labels:
val firstThree = listOf(1, 2, 3, 4, 5).filter(fun(x: Int): Boolean {
if (x > 3) return false
return true
})
Inside a lambda, return returns from the enclosing function, not the lambda. To return from the lambda only, use return@filter. Anonymous functions don't have that confusion.
For 99% of cases, lambdas are clearer. Anonymous functions are an escape hatch.
Common mistakes
Trying it in multi-arg lambdas. Doesn't exist. { x, y -> x + y } requires names.
return from a lambda. Returns from the outer function. To return from the lambda only, use return@label:
list.forEach {
if (it < 0) return@forEach // skip this iteration
println(it)
}
Storing function calls instead of functions. val x = printName("Alice") calls and stores Unit. Use val x = ::printName or assign a lambda.
Lambda with side effects in map. list.map { println(it) } works but is misleading — map is for transformations. Use forEach for side effects.
Implicit it shadowing outer it. Nested lambdas with implicit it confuse readers. Always name the parameter when nesting.
What's next
Episode 28: List of 10 numbers, lambda to find evens. Combines (1..10).toList() with filter { it % 2 == 0 }.
Recap
Single-parameter lambdas use it as the implicit name (or explicit name if clearer). forEach { println(it) } for side-effecting iteration. forEachIndexed if you need the position. Anonymous-function syntax (fun(x): T { ... }) exists but is rarely used. Use trailing-lambda syntax fn(args) { lambda } for readability. Side effects → forEach; transforms → map; predicates → filter.
Next episode: filter evens from 1..10.