Ce face lambda
O expresie lambda se scrie între acolade: { a: Int, b: Int -> a + b }. Înainte de -> sunt parametrii, după el este corpul. Ultima expresie din corp este rezultatul; nu se scrie return. Tipul unei lambda este un tip funcție, de exemplu (Int, Int) -> Int.
Dacă lambda are un singur parametru, poți să nu-l numești: se numește automat it. Dacă lambda este ultimul argument al unei funcții, se scrie după paranteze (trailing lambda): lista.filter { it > 5 }. Așa arată aproape tot codul cu colecții din Kotlin.
O lambda poate folosi și modifica variabile din jurul ei (closure). Pentru a ieși devreme dintr-o lambda folosești o etichetă: return@forEach sare la următorul element. Un return simplu ar ieși din funcția care o conține (doar la funcțiile inline).
Exemple
Exemplul 1: Lambda în variabile
aduna are tipul scris explicit; la dublu tipul parametrului este scris în lambda. Ultima expresie din descrie este rezultatul.
fun main() {
val aduna: (Int, Int) -> Int = { a, b -> a + b }
val dublu = { x: Int -> x * 2 }
val descrie = { nota: Int ->
val text = if (nota >= 5) "promovat" else "nepromovat"
"Nota $nota: $text"
}
println(aduna(7, 5))
println(dublu(21))
println(descrie(9))
println(descrie(4))
}
Rezultat
12
42
Nota 9: promovat
Nota 4: nepromovat
Exemplul 2: it și lambda după paranteze
Funcțiile de colecții primesc lambda ca ultim argument. it este elementul curent.
fun main() {
val preturi = listOf(12.5, 99.0, 45.0, 150.0)
val ieftine = preturi.filter { it < 50 }
val cuTva = preturi.map { pret -> pret * 1.21 }
val total = preturi.sumOf { it }
println("Sub 50 lei: $ieftine")
println("Cu TVA: ${cuTva.map { "%.2f".format(it) }}")
println("Total: $total lei")
println("Sortate descrescător: ${preturi.sortedByDescending { it }}")
}
Rezultat
Sub 50 lei: [12.5, 45.0]
Cu TVA: [15.13, 119.79, 54.45, 181.50]
Total: 306.5 lei
Sortate descrescător: [150.0, 99.0, 45.0, 12.5]
Exemplul 3: Closure și return@eticheta
Lambda modifică variabila suma din afara ei. return@forEach sare peste notele invalide, fără să oprească bucla.
fun main() {
val note = listOf(9, -1, 7, 11, 10)
var suma = 0
var valide = 0
note.forEach { nota ->
if (nota !in 1..10) {
println("Ignor nota $nota")
return@forEach
}
suma += nota
valide++
}
println("Media notelor valide: ${suma.toDouble() / valide}")
}
Rezultat
Ignor nota -1
Ignor nota 11
Media notelor valide: 8.666666666666666
Greșeli frecvente
- Scrierea lui
return valoareîntr-o lambda: rezultatul unei lambda este ultima expresie. Unreturnsimplu încearcă să iasă din funcția exterioară (și nu compilează dacă funcția nu esteinline). - Folosirea lui
itîn lambda imbricate:itse referă la lambda cea mai apropiată. Dă nume explicite parametrilor când ai mai multe niveluri. - Confuzia dintre
{ x -> x * 2 }(lambda) și{ x * 2 }fără parametru declarat: în al doilea cazxtrebuie să existe deja în jur.
Comenzi înrudite
Funcții de ordin superior: O funcție de ordin superior primește o funcție ca parametru sau returnează o funcție.fun: fun declară o funcție: un bloc de cod cu nume, care primește parametri și poate returna un rezultat.inline, noinline și crossinline: inline copiază corpul funcției și lambda-urile ei în locul apelului; noinline și crossinline controlează lambda-urile primite.Funcții de extensie: O funcție de extensie adaugă o metodă nouă unui tip existent (String, Int, List), fără să modifici clasa.Iterable.forEach: Execută o acțiune pentru fiecare element, în ordine; forEachIndexed primește și poziția.