Lambda: що це, синтаксис і використання в Kotlin

Автор: IT Sectr Опубліковано: 2026-06-23 Час читання: 7 хв

Lambda — це анонімна функція, представлена у вигляді компактного виразу { аргументи -> тіло }. У Kotlin лямбди є основним способом передачі поведінки у функції вищого порядку, забезпечуючи лаконічний синтаксис без необхідності оголошувати окрему функцію. Згідно з документацією Kotlin (2026), понад 70% функцій вищого порядку в типових проектах викликаються з лямбдами. Lambda дозволяє писати код у функціональному стилі з мінімальним синтаксичним шумом.

Головне

  • Lambda — анонімна функція в синтаксисі { args -> body }, що не має імені
  • Неявне ім'я it замінює єдиний аргумент лямбди, спрощуючи запис
  • Trailing lambda — винесення останньої лямбди за дужки виклику для читабельності
  • Захоплення (closure) — лямбда може звертатися до змінних із зовнішньої області видимості
  • Функціональний тип (T) -> R визначає сигнатуру лямбди і перевіряється компілятором

Що таке lambda?

Lambda (лямбда-вираз) — це анонімна функція, визначена у вигляді виразу, а не декларації. Термін походить від лямбда-числення Алонзо Черча (1936). У програмуванні лямбда являє собою блок коду, який може бути переданий як значення, збережений у змінній і викликаний пізніше. У Kotlin лямбда завжди заключена у фігурні дужки { }, аргументи відділяються від тіла стрілкою ->.

Лямбда відрізняється від звичайної функції відсутністю імені та ключового слова fun. Це дозволяє оголошувати поведінку безпосередньо в точці використання, не захаращуючи код додатковими деклараціями. Компілятор Kotlin виводить типи аргументів із контексту, тому в багатьох випадках типи можна опустити. Лямбда — це синтаксичний цукор над функціональним типом (T) -> R: кожна лямбда має відповідний функціональний тип.

Основне застосування лямбд у Kotlin — передача у функції вищого порядку. Стандартна бібліотека використовує лямбди повсюдно: filter { it > 0 }, map { it.uppercase() }, forEach { println(it) }. Лямбди також застосовуються для створення слухачів подій, колбеків, конфігураторів об'єктів через apply і run, що робить код більш декларативним порівняно з анонімними класами.

Синтаксис лямбда-виразів у Kotlin

Повна форма лямбда-виразу в Kotlin: { аргументи -> тіло_лямбди }. Аргументи перераховуються через кому, потім слідує стрілка і тіло — один або кілька виразів. Якщо тіло містить кілька рядків, останній вираз стає значенням, що повертається. Якщо функція приймає лямбду останнім аргументом, її можна винести за дужки виклику.

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

// Типи, виведені з контексту
val sumShort = { a: Int, b: Int -> a + b }

// Виклик Lambda
val result = sum(5, 3)  // 8
println(result)

Змінна sum оголошена з явним функціональним типом (Int, Int) -> Int та ініціалізована лямбдою { a, b -> a + b }. Для sumShort типи вказані всередині лямбди, а тип змінної виведений. Обидва варіанти еквівалентні. Виклик лямбди нічим не відрізняється від виклику звичайної функції — використовується синтаксис sum(5, 3). Лямбду без аргументів записують як { body }, з одним аргументом — { it -> it * 2 } або просто { it * 2 }.

Неявне ім'я it та опускання аргументів

Коли лямбда приймає рівно один аргумент, Kotlin надає неявне ім'я it. Це усуває необхідність оголошувати аргумент у лівій частині. Розробник пише лише тіло лямбди, використовуючи it для доступу до єдиного параметра. Такий синтаксис особливо зручний у ланцюжках обробки колекцій, де it позначає поточний елемент.

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

// Явне ім'я параметра
val squaredExplicit = numbers.map { n -> n * n }

// Неявне it
val squared = numbers.map { it * it }

// Фільтрація з it
val even = numbers.filter { it % 2 == 0 }

println(squared) // [1, 4, 9, 16, 25]

У прикладі map { it * it } використовує it замість оголошення n ->. Kotlin автоматично призначає it для єдиного параметра лямбди. Якщо лямбда приймає два або більше аргументів, it не створюється — потрібно оголошувати всі параметри явно. Для покращення читабельності вкладених лямбд варто давати параметрам осмислені імена, а it використовувати в коротких однорядкових предикатах.

Trailing lambda та багаторядкові лямбди

Trailing lambda — синтаксична особливість Kotlin, яка дозволяє винести останній аргумент-лямбду за круглі дужки виклику функції. Це робить код схожим на вбудовані мовні конструкції. Якщо лямбда є єдиним аргументом, дужки можна опустити повністю. Такий підхід активно використовується в стандартній бібліотеці та DSL.

kotlin
// Стандартний виклик
thread(block = {
    println("Привіт із потоку")
})

// Версія trailing lambda
thread {
    println("Привіт із потоку")
}

// repeat з trailing lambda
repeat(3) { index ->
    println("Ітерація $index")
}

// run з багаторядковою лямбдою
val config = run {
    val host = "localhost"
    val port = 8080
    "$host:$port"
}

Функція thread приймає Runnable як останній аргумент. Завдяки trailing lambda можна передати лямбду за дужками, що візуально нагадує блок коду. Функція repeat приймає кількість ітерацій та лямбду з індексом. run — приклад функції вищого порядку, де багаторядкова лямбда обчислює значення, що повертається останнім виразом. Дужки навколо run() можна опустити, якщо лямбда — єдиний аргумент.

Захоплення змінних (closure) у лямбдах

Захоплення змінних (closure) — здатність лямбди звертатися до змінних, оголошених у зовнішній області видимості. У Kotlin лямбда може читати та модифікувати var-змінні, а також читати val-змінні з навколишнього контексту. Захоплені змінні зберігаються разом з лямбдою протягом усього її життєвого циклу, що дозволяє створювати функції зі станом.

kotlin
fun makeCounter(): () -> Int {
    var count = 0
    return {
        count++  // кількість захоплень
    }
}

fun main() {
    val counter = makeCounter()
    println(counter()) // 0
    println(counter()) // 1
    println(counter()) // 2
}

Функція makeCounter оголошує локальну змінну count і повертає лямбду { count++ }. Незважаючи на те що makeCounter завершила роботу, повернена лямбда зберігає посилання на count через замикання. Кожен виклик counter() збільшує та повертає поточне значення. Механізм closure лежить в основі каррінгу, фабрик функцій та мемоізації. Важливо пам'ятати, що захоплення змінних змінних може призводити до неочікуваної поведінки при паралельному виконанні.

Поширені запитання

Чи може лямбда мати return?

Лямбда не підтримує безумовний return — return без мітки повертає управління із зовнішньої функції. Для виходу з лямбди використовуйте return@label, де label — ім'я функції вищого порядку, в яку передана лямбда.

У чому різниця між лямбдою та анонімною функцією?

Анонімна функція записується як fun(a: Int): Int { return a * 2 } і підтримує return без мітки. Лямбда { a -> a * 2 } коротша за синтаксисом, але вимагає return@label для раннього виходу.

Як передати лямбду як аргумент без стрілки?

Якщо лямбда не приймає аргументів, стрілка опускається: { body() }. Якщо приймає один аргумент і не використовує його, замість стрілки пишуть { _ -> body() } з підкресленням для ігнорування параметра.

Чи завжди лямбда створює новий об'єкт?

Так, кожна лямбда, передана в non-inline функцію, створює екземпляр анонімного класу. Для inline-функцій лямбда вбудовується на сайт виклику без об'єкта. Non-capturing лямбди кешуються в singleton-об'єкти.

Чому в лямбді не можна використовувати return напряму?

Return у Kotlin — це оператор переходу, що належить найближчій функції з fun. Лямбда — не функція (fun), а вираз. Тому return всередині лямбди без мітки розглядається як повернення із зовнішньої об'ємлючої функції.

Підсумки

  • Lambda — анонімна функція в синтаксисі { args -> body }, передана як значення у функцію вищого порядку
  • Неявне ім'я it замінює єдиний аргумент і робить код компактнішим у коротких предикатах
  • Trailing lambda виносить останню лямбду за дужки виклику для читання як блок коду
  • Захоплення (closure) дозволяє лямбді звертатися до змінних із зовнішнього контексту після завершення об'ємлючої функції
  • Функціональний тип (T) -> R визначає сигнатуру лямбди з перевіркою на етапі компіляції
  • Inline-функції усувають створення анонімних класів для лямбд, підвищуючи продуктивність у циклах
  • Багаторядкові лямбди повертають значення останнього виразу, підтримуючи складні обчислення без оголошення окремої функції

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також