Lambda — egy névtelen függvény, amely kompakt kifejezés formájában jelenik meg { argumentumok -> törzs }. Kotlinban a lambdák az elsődleges módjai a viselkedés átadásának a magasabb rendű függvényeknek (higher-order functions), tömör szintaxist biztosítva anélkül, hogy külön függvényt kellene deklarálni. A Kotlin dokumentáció (2026) szerint a tipikus projektekben a magasabb rendű függvények több mint 70%-át lambdákkal hívják meg. Lambda lehetővé teszi a kód funkcionális stílusban történő írását minimális szintaktikai zajjal.
Főbb pontok
Lambda (lambda kifejezés) — egy névtelen függvény, amely kifejezésként van definiálva, nem deklarációként. A kifejezés Alonzo Church (1936) lambda-kalkulusából származik. A programozásban a lambda egy olyan kódblokkot képvisel, amely értékként átadható, változóban tárolható és később meghívható. Kotlinban a lambda mindig kapcsos zárójelek { } közé van zárva, az argumentumokat a -> nyíl választja el a törzstől.
A lambda abban különbözik a szokásos függvénytől, hogy hiányzik a neve és a fun kulcsszó. Ez lehetővé teszi a viselkedés közvetlen deklarálását a használat helyén, anélkül, hogy a kódot további deklarációkkal zsúfolná. A Kotlin fordító kikövetkezteti az argumentumok típusait a kontextusból, így sok esetben a típusok elhagyhatók. A lambda szintaktikai cukor a funkcionális típus (T) -> R felett: minden lambdának megvan a megfelelő funkcionális típusa.
A lambdák fő alkalmazása Kotlinban a magasabb rendű függvényekbe (higher-order functions) való átadás. A szabványos könyvtár mindenhol lambdákat használ: filter { it > 0 }, map { it.uppercase() }, forEach { println(it) }. A lambdákat eseményfigyelők, visszahívások, objektumkonfigurátorok létrehozására is használják apply és run segítségével, ami deklaratívabbá teszi a kódot a névtelen osztályokhoz képest.
A lambda kifejezés teljes formája Kotlinban: { argumentumok -> lambda_törzs }. Az argumentumok vesszővel vannak felsorolva, majd a nyíl és a törzs következik — egy vagy több kifejezés. Ha a törzs több sort tartalmaz, az utolsó kifejezés lesz a visszatérési érték. Ha a függvény lambdát fogad el utolsó argumentumként, az kiemelhető a hívás zárójelein kívülre.
val sum: (Int, Int) -> Int = { a, b -> a + b }
// Kontextusból kikövetkeztetett típusok
val sumShort = { a: Int, b: Int -> a + b }
// Lambda hívás
val result = sum(5, 3) // 8
println(result)
A sum változó explicit funkcionális típussal (Int, Int) -> Int van deklarálva, és a { a, b -> a + b } lambdával inicializálva. A sumShort esetében a típusok a lambdán belül vannak megadva, a változó típusa pedig kikövetkeztetve. Mindkét változat egyenértékű. A lambda meghívása nem különbözik egy szokásos függvény meghívásától — a sum(5, 3) szintaxis használatos. Az argumentum nélküli lambdát { body }-ként írjuk, egy argumentummal — { it -> it * 2 } vagy egyszerűen { it * 2 }.
Amikor a lambda pontosan egy argumentumot fogad el, Kotlin implicit it nevet biztosít. Ez kiküszöböli az argumentum bal oldali deklarálásának szükségességét. A programozó csak a lambda törzsét írja, az it-t használva az egyetlen paraméter eléréséhez. Ez a szintaxis különösen kényelmes a gyűjteményfeldolgozási láncokban, ahol az it az aktuális elemet jelöli.
val numbers = listOf(1, 2, 3, 4, 5)
// Explicit paraméternév
val squaredExplicit = numbers.map { n -> n * n }
// Implicit it
val squared = numbers.map { it * it }
// Szűrés it-vel
val even = numbers.filter { it % 2 == 0 }
println(squared) // [1, 4, 9, 16, 25]
A map { it * it } példában it használatos az n -> deklaráció helyett. A Kotlin automatikusan hozzárendeli az it-t a lambda egyetlen paraméteréhez. Ha a lambda két vagy több argumentumot fogad el, az it nem jön létre — minden paramétert explicit módon kell deklarálni. A beágyazott lambdák jobb olvashatósága érdekében érdemes a paramétereknek értelmes neveket adni, és az it-t rövid egysoros predikátumokban használni.
Trailing lambda (záró lambda) — a Kotlin szintaktikai jellemzője, amely lehetővé teszi az utolsó argumentum-lambda kiemelését a függvényhívás kerek zárójelein kívülre. Ez hasonlóvá teszi a kódot a beépített nyelvi konstrukciókhoz. Ha a lambda az egyetlen argumentum, a zárójelek teljesen elhagyhatók. Ezt a megközelítést aktívan használják a szabványos könyvtárban és a DSL-ben.
// Szabványos hívás
thread(block = {
println("Helló a szálból")
})
// Trailing lambda verzió
thread {
println("Helló a szálból")
}
// repeat trailing lambdával
repeat(3) { index ->
println("Iteráció $index")
}
// run többsoros lambdával
val config = run {
val host = "localhost"
val port = 8080
"$host:$port"
}
A thread függvény Runnable-t fogad el utolsó argumentumként. A trailing lambdának köszönhetően a lambda a zárójeleken kívül is átadható, ami vizuálisan egy kódblokkra emlékeztet. A repeat függvény az iterációk számát és egy indexet tartalmazó lambdát fogad el. A run — egy magasabb rendű függvény példája, ahol egy többsoros lambda kiszámítja az utolsó kifejezés által visszaadott értéket. A run() körüli zárójelek elhagyhatók, ha a lambda az egyetlen argumentum.
Változók befogása (closure) — a lambda azon képessége, hogy hozzáférjen a külső láthatósági tartományban deklarált változókhoz. Kotlinban a lambda olvashatja és módosíthatja a var változókat, valamint olvashatja a val változókat a környező kontextusból. A befogott változók a lambdával együtt tárolódnak annak teljes életciklusa során, lehetővé téve állapottal rendelkező függvények létrehozását.
fun makeCounter(): () -> Int {
var count = 0
return {
count++ // befogások száma
}
}
fun main() {
val counter = makeCounter()
println(counter()) // 0
println(counter()) // 1
println(counter()) // 2
}
A makeCounter függvény deklarál egy lokális count változót és visszaadja a { count++ } lambdát. Annak ellenére, hogy a makeCounter befejezte a munkáját, a visszaadott lambda a closure segítségével megtartja a count-ra való hivatkozást. Minden counter() hívás növeli és visszaadja az aktuális értéket. A closure mechanizmus képezi a currying, a függvénygyárak és a memoizáció alapját. Fontos megjegyezni, hogy a változtatható változók befogása váratlan viselkedéshez vezethet párhuzamos végrehajtás során.
Gyakran ismételt kérdések
Lambda nem támogatja a feltétel nélküli return-t — a címke nélküli return visszaadja a vezérlést a külső függvénynek. A lambdából való kilépéshez használja a return@label-t, ahol a label annak a magasabb rendű függvénynek a neve, amelynek a lambdát átadták.
Névtelen függvény fun(a: Int): Int { return a * 2 }-ként írható, és támogatja a címke nélküli return-t. Lambda { a -> a * 2 } szintaktikailag rövidebb, de a korai kilépéshez return@label-t igényel.
Ha a lambda nem fogad el argumentumokat, a nyíl elhagyható: { body() }. Ha egy argumentumot fogad el és nem használja, a nyíl helyett { _ -> body() } írandó aláhúzással a paraméter figyelmen kívül hagyásához.
Igen, minden nem inline függvénynek átadott lambda létrehoz egy névtelen osztály példányt. Inline függvények esetén a lambda a hívás helyére kerül beillesztésre objektum létrehozása nélkül. A nem befogó (non-capturing) lambdák singleton objektumokba vannak gyorsítótárazva.
Return Kotlinban egy ugró operátor, amely a legközelebbi fun-os függvényhez tartozik. A lambda nem függvény (fun), hanem kifejezés. Ezért a lambdán belüli címke nélküli return a külső körülvevő függvényből való visszatérésnek minősül.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is