Študijné materiály

Funkcie vyššieho rádu a lambda funkcie

Funkcia vyššieho rádu je funkcia, ktorá prijíma inú funkciu ako parameter alebo funkciu vracia. Lambda je funkcia bez mena, ktorú vieme uložiť do premennej alebo odovzdať inej funkcii.

fun main() {
    val sucet = { a: Int, b: Int -> a + b }

    println(sucet(3, 5)) // 8
}

Typ lambda funkcie zapisujeme v tvare (typParametra) -> navratovyTyp. Lambda bez parametrov, ktorá nič nevracia, má typ () -> Unit.

val pozdrav: () -> Unit = { println("Ahoj") }
val druhaMocnina: (Int) -> Int = { cislo -> cislo * cislo }

fun main() {
    pozdrav()
    println(druhaMocnina(4)) // 16
}

25.1.1 Funkcia ako parameter

Do funkcie môžeme odovzdať lambdu rovnako ako číslo alebo text. V nasledujúcom príklade funkcia spracuj prijme číslo a postup, ktorý sa má nad číslom vykonať.

fun spracuj(cislo: Int, operacia: (Int) -> Int): Int {
    return operacia(cislo)
}

fun main() {
    val vysledok = spracuj(5) { it * 2 }
    println(vysledok) // 10
}

Ak má lambda práve jeden parameter, nemusíme mu dávať meno. Kotlin ho sprístupní pod predvoleným názvom it.

val velkePismena: (String) -> String = { it.uppercase() }

fun main() {
    println(velkePismena("kotlin")) // KOTLIN
}

25.1.2 Trailing lambda

Ak je posledným parametrom funkcie lambda, môžeme ju zapísať za zátvorky volania. Tento zápis sa v Kotline používa veľmi často.

fun opakuj(pocet: Int, akcia: () -> Unit) {
    repeat(pocet) {
        akcia()
    }
}

fun main() {
    opakuj(3) {
        println("Ahoj")
    }
}

25.1.3 Funkcia ako návratová hodnota

Funkcia vyššieho rádu môže vytvoriť a vrátiť aj inú funkciu.

fun vytvorNasobenie(nasobitel: Int): (Int) -> Int {
    return { cislo -> cislo * nasobitel }
}

fun main() {
    val zdvojnasob = vytvorNasobenie(2)
    println(zdvojnasob(7)) // 14
}

25.1.4 Lambdy v kolekciách

Funkcie map, filter a forEach prijímajú lambdu. Vďaka tomu môžeme stručne spracovať zoznam.

fun main() {
    val cisla = listOf(1, 2, 3, 4, 5)

    val parne = cisla.filter { it % 2 == 0 }
    val druheMocniny = cisla.map { it * it }

    parne.forEach { println(it) }
    println(druheMocniny) // [1, 4, 9, 16, 25]
}

Lambda môže pristupovať aj k premenným z okolitého kódu. Takúto lambdu nazývame closure.

Úlohy

Úloha 1

Vytvor lambda funkciu, ktorá prijme dve čísla a vráti ich väčšie číslo. Zavolaj ju pre aspoň dve rôzne dvojice.

Úloha 2

Napíš funkciu vypisAkciu, ktorá prijme text a lambda funkciu typu (String) -> Unit. Funkcia odovzdá text lambde. Zavolaj ju s lambdou, ktorá text vypíše veľkými písmenami.

Úloha 3

Pre zoznam celých čísel použi filter na výber kladných párnych čísel a následne map na ich vynásobenie desiatimi. Vypíš výsledný zoznam.