Skip to main content

Kotlin Lambda Basics

Introduction

Lambda expressions (or simply "lambdas") are one of the most powerful features in Kotlin. They allow you to write concise code by defining anonymous functions that can be passed as arguments, stored in variables, or returned from other functions. If you're coming from Java, think of lambdas as a more elegant way to implement interfaces with a single method.

In this tutorial, we'll explore the basics of Kotlin lambdas, understand their syntax, and see how they can make your code more readable and maintainable.

What is a Lambda Expression?

A lambda expression is essentially a function without a name (anonymous function) that can be used as an expression. In Kotlin, lambdas are enclosed in curly braces { }.

Here's the general syntax of a lambda expression in Kotlin:

kotlin
{ parameter1: Type1, parameter2: Type2 -> body_of_lambda }

The parameters and their types are declared before the arrow ->, and the body of the lambda follows after it.

Basic Lambda Syntax

Let's start with a simple lambda example:

kotlin
val sum = { a: Int, b: Int -> a + b }

In this example:

  • We've created a lambda that takes two Int parameters and returns their sum
  • The lambda is assigned to a variable named sum
  • We can now use sum as a function

To invoke this lambda, we call it like a regular function:

kotlin
val result = sum(5, 3)
println(result) // Output: 8

Type Inference with Lambdas

Kotlin's type inference works with lambdas too. When the compiler can determine the parameter types from context, you can omit them:

kotlin
// Lambda with explicit parameter types
val multiply: (Int, Int) -> Int = { a: Int, b: Int -> a * b }

// Lambda with type inference - parameter types are omitted
val multiply: (Int, Int) -> Int = { a, b -> a * b }

In both cases, multiply is a lambda that accepts two integers and returns their product.

Lambda as the Last Parameter

When a function's last parameter is a lambda, you can pass it outside the parentheses:

kotlin
fun performOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}

// Regular way to call
val result1 = performOperation(5, 3, { a, b -> a + b })

// Using the trailing lambda syntax
val result2 = performOperation(5, 3) { a, b -> a + b }

Both calls do the same thing, but the trailing lambda syntax is more readable and is a common pattern in Kotlin.

it: Implicit Name for Single Parameter

If your lambda has only one parameter, you can omit the parameter declaration and use it as the implicit name:

kotlin
val numbers = listOf(1, 2, 3, 4, 5)

// Using explicit parameter
numbers.filter({ number -> number > 3 })

// Using the implicit 'it' parameter
numbers.filter { it > 3 }

The result in both cases is [4, 5]. The second version is more concise and very common in Kotlin code.

Real-world Examples

Example 1: Filtering a List

One of the most common uses of lambdas is with collection operations:

kotlin
val fruits = listOf("apple", "banana", "cherry", "date", "elderberry")

// Filter fruits that start with 'a'
val aFruits = fruits.filter { it.startsWith('a') }
println(aFruits) // Output: [apple]

// Filter fruits with length > 5
val longFruits = fruits.filter { it.length > 5 }
println(longFruits) // Output: [banana, cherry, elderberry]

Example 2: Button Click Listener (Android)

In Android development, lambdas are frequently used for event handling:

kotlin
// Traditional anonymous class (Java style)
button.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
// handle click
toast("Button clicked!")
}
})

// Same thing with Kotlin lambda
button.setOnClickListener {
toast("Button clicked!")
}

The lambda version is much more concise and readable.

Example 3: Custom Sorting with lambdas

kotlin
data class Person(val name: String, val age: Int)

val people = listOf(
Person("Alice", 29),
Person("Bob", 31),
Person("Charlie", 25)
)

// Sort by age
val sortedByAge = people.sortedBy { it.age }
println(sortedByAge)
// Output: [Person(name=Charlie, age=25), Person(name=Alice, age=29), Person(name=Bob, age=31)]

// Sort by name length
val sortedByNameLength = people.sortedBy { it.name.length }
println(sortedByNameLength)
// Output: [Person(name=Bob, age=31), Person(name=Alice, age=29), Person(name=Charlie, age=25)]

Lambda with Receiver

Kotlin also supports lambdas with receivers, where the lambda has access to the methods and properties of a specified object without qualifier. This is a more advanced topic, but here's a simple example:

kotlin
val greet: String.() -> String = { "Hello, $this!" }

val greeting = "World".greet()
println(greeting) // Output: Hello, World!

In this example, String.() means that within the lambda, this refers to a String instance.

Summary

In this tutorial, we've covered the basics of Kotlin lambdas:

  • Lambda expressions are anonymous functions that can be passed around as values
  • The basic syntax is { parameters -> body }
  • Type inference allows for more concise code
  • For single-parameter lambdas, you can use it instead of naming the parameter
  • Trailing lambda syntax makes code more readable when a lambda is the last parameter
  • Lambdas are commonly used with collections, for event handling, and in many other scenarios

Lambdas are a cornerstone of functional programming in Kotlin and mastering them will greatly improve your code quality and expressiveness.

Exercises

To practice your understanding of lambdas, try these exercises:

  1. Write a lambda that returns the square of a number, then use it to transform a list of integers.
  2. Create a function that takes a name and a lambda, then calls the lambda with the name as an argument.
  3. Use the filter and map functions with lambdas to find all even numbers in a list and multiply them by 3.
  4. Write a lambda with receiver that adds a prefix to a string.

Additional Resources

Happy coding with Kotlin lambdas!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)