← All courses

Lambdas, Higher-Order & Extension Functions

🗓 May 31, 2026 ⏱ 2 min read

Lambdas: functions as values

A lambda is a small anonymous function you can store in a variable or pass to another function. This is the foundation of Kotlin’s expressive style.

val square = { x: Int -> x * x }
println(square(5))    // 25

val greet = { name: String -> "Hi, $name" }
println(greet("Anand"))

Higher-order functions

A higher-order function takes a function as a parameter or returns one. This lets you pass behaviour, not just data.

fun repeatAction(times: Int, action: (Int) -> Unit) {
    for (i in 0 until times) action(i)
}

repeatAction(3) { index -> println("Run #$index") }

When the last parameter is a lambda, you can move it outside the parentheses (trailing-lambda syntax) — that’s why so much Kotlin code reads like doSomething { ... }.

The implicit it

If a lambda has a single parameter, you can skip naming it and use it:

val nums = listOf(1, 2, 3, 4)
val evens = nums.filter { it % 2 == 0 }   // it = each number

Extension functions

Kotlin lets you add new functions to existing classes — even ones you didn’t write, like String — without subclassing. These are called extension functions.

fun String.shout(): String = this.uppercase() + "!"
println("hello".shout())   // HELLO!

// a genuinely useful one
fun String.isValidEmail(): Boolean =
    this.contains("@") && this.contains(".")

if ("test@site.com".isValidEmail()) println("looks valid")

Inside an extension, this refers to the object the function is called on (the “receiver”). Android’s Kotlin extensions (KTX) use this idea everywhere.

Returning functions

fun multiplier(factor: Int): (Int) -> Int = { number -> number * factor }
val triple = multiplier(3)
println(triple(10))   // 30

Common mistakes

  • Over-nesting lambdas until the code is unreadable — extract a named function when it gets deep.
  • Using it when there are multiple meaningful parameters — name them.
  • Writing utility classes full of static helpers instead of clean extension functions.
Summary: Lambdas pass behaviour as values; higher-order functions accept them; extension functions add methods to existing types. Together they make Kotlin concise and expressive.