How do I use lambdas and anonymous functions in Kotlin?

In Kotlin, lambdas and anonymous functions are fundamental features used for functional programming. They allow you to write concise and flexible code. Here’s an overview on how to use them:


1. Lambda Expressions

A lambda is an anonymous function defined using curly braces {}. It’s a short way to declare a function without explicitly naming it.

Syntax:

{ parameter(s) -> body }

Example:

// Lambda that takes two integers and returns their sum
val sum = { a: Int, b: Int -> a + b }

// Using the lambda
println(sum(3, 5)) // Output: 8

2. Single-Parameter Lambdas

If a lambda has only one parameter, you can omit the parameter declaration and use it instead (an implicit name for the parameter).

Example:

val square = { it * it } // 'it' is the implicit name for the parameter

println(square(4)) // Output: 16

3. Passing Lambdas to Higher-Order Functions

You can pass lambdas as arguments to functions that take other functions as parameters, referred to as higher-order functions.

Example:

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

// Passing a lambda
val result = calculate(4, 5) { x, y -> x + y }
println(result) // Output: 9

4. Anonymous Functions

An anonymous function is similar to a lambda but explicitly uses the function keyword. It allows you to specify return types.

Example:

val multiply = fun(a: Int, b: Int): Int {
    return a * b
}

println(multiply(3, 4)) // Output: 12

5. Differences Between Lambdas and Anonymous Functions

  • Lambdas implicitly infer the return type (using the last expression), whereas anonymous functions can have explicitly declared return types.
  • Lambdas cannot use a return keyword for the enclosing function, while anonymous functions can.

6. Inline Lambda Usage

For functions like map, filter, or forEach, lambdas can be used to process collections concisely. These functions come from Kotlin’s standard library.

Example:

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

// Transform each element using a lambda
val doubled = numbers.map { it * 2 }
println(doubled) // Output: [2, 4, 6, 8, 10]

// Filter using a lambda
val evens = numbers.filter { it % 2 == 0 }
println(evens) // Output: [2, 4]

7. Lambda as Return Type

You can assign functions returning lambdas to variables.

Example:

fun createMultiplier(factor: Int): (Int) -> Int {
    return { number -> number * factor }
}

val timesThree = createMultiplier(3)
println(timesThree(5)) // Output: 15

8. Default Parameters in Lambda

While lambdas themselves don’t support default arguments, you can achieve a similar effect by wrapping them in a function that provides default behavior.

Example:

fun greet(name: String, message: (String) -> String = { "Hello, $it!" }) {
    println(message(name))
}

// Using the default lambda
greet("John") // Output: Hello, John!

// Customizing the lambda
greet("John") { "Hi, $it! Welcome back!" } // Output: Hi, John! Welcome back!

9. Higher-Order Functions Inline and Crossinline

When using lambdas in performance-critical situations, consider using the inline or crossinline modifier, which instructs the compiler to inline the lambda directly into the calling function.

Example:

inline fun perform(action: () -> Unit) {
    action()
}

perform {
    println("This lambda was inlined!")
}

Summary

  • Lambdas: { parameter(s) -> body }
  • Single-parameter lambdas can use it as the implicit name.
  • Anonymous functions use the fun keyword and can declare explicit return types.
  • You can pass lambdas to higher-order functions for concise and flexible processing.
  • Use collections functions like map, filter, and forEach to apply lambdas efficiently.

The combination of lambdas and Kotlin’s higher-order functions lets you write clear and concise functional code!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.