fun în Kotlin

Funcții și lambda Kotlin 1.0

fun declară o funcție: un bloc de cod cu nume, care primește parametri și poate returna un rezultat.

Sintaxă
fun nume(param: Tip, altul: Tip = valoareImplicita): TipRezultat {
    return rezultat
}

fun nume(param: Tip) = expresie      // funcție cu corp-expresie

Ce face fun

Cuvântul cheie fun declară o funcție. După nume vin parametrii în paranteze, fiecare cu tipul lui (pret: Double), apoi, după :, tipul rezultatului. Rezultatul se dă înapoi cu return. Dacă funcția nu returnează nimic util, tipul ei este Unit și nu trebuie scris.

Când tot corpul este o singură expresie, poți scrie fun dublu(x: Int) = x * 2: fără acolade și fără return, iar tipul rezultatului este dedus de compilator. Parametrii pot avea valori implicite (tva: Double = 0.19), iar la apel poți folosi argumente cu nume (pretFinal(100.0, tva = 0.09)), ceea ce face apelurile ușor de citit.

Funcțiile pot sta la nivelul de sus al fișierului (fără clasă), în clase (metode) sau chiar în interiorul altei funcții (funcții locale). Parametrii sunt mereu val: nu le poți schimba valoarea în corpul funcției.

Parametri

Parametru Descriere
param: Tip Un parametru și tipul lui. Tipul este obligatoriu la parametri.
= valoare Opțional. Valoarea folosită când apelul nu dă argumentul.
: TipRezultat Tipul valorii returnate. Lipsește pentru Unit sau la funcțiile cu corp-expresie.

Ce returnează

Valoarea dată de return (sau de expresie, la corp-expresie). Fără rezultat: Unit.

Exemple

Exemplul 1: Funcție cu bloc și funcție cu corp-expresie

pretCuTva are corp cu acolade și return. esteScump este scrisă pe un rând; tipul Boolean este dedus.

fun pretCuTva(pret: Double): Double {
    val tva = pret * 0.21
    return pret + tva
}

fun esteScump(pret: Double) = pret > 100

fun main() {
    val total = pretCuTva(50.0)
    println("Total: $total lei")
    println("Este scump? ${esteScump(total)}")
    println("Este scump 150? ${esteScump(150.0)}")
}

Rezultat

Total: 60.5 lei
Este scump? false
Este scump 150? true

Exemplul 2: Valori implicite și argumente cu nume

Al doilea și al treilea parametru au valori implicite. Cu argumente cu nume poți sări peste unul dintre ei sau îi poți da în altă ordine.

fun salut(nume: String, oras: String = "București", formal: Boolean = false): String {
    val inceput = if (formal) "Bună ziua" else "Salut"
    return "$inceput, $nume din $oras!"
}

fun main() {
    println(salut("Ana"))
    println(salut("Mihai", "Iași"))
    println(salut("Elena", formal = true))
    println(salut(oras = "Cluj", nume = "Andrei"))
}

Rezultat

Salut, Ana din București!
Salut, Mihai din Iași!
Bună ziua, Elena din București!
Salut, Andrei din Cluj!

Exemplul 3: Funcție locală și funcție fără rezultat (Unit)

afiseazaRaport nu returnează nimic, deci tipul ei este Unit. În interiorul ei, funcția locală linie poate fi folosită doar acolo.

fun afiseazaRaport(note: Map<String, Int>) {
    fun linie(nume: String, nota: Int) = println("${nume.padEnd(8)} $nota")

    println("Raport note")
    for ((nume, nota) in note) linie(nume, nota)
}

fun main() {
    val rezultat = afiseazaRaport(mapOf("Ana" to 10, "Mihai" to 8, "Ioana" to 9))
    println("Rezultatul funcției: $rezultat")
}

Rezultat

Raport note
Ana      10
Mihai    8
Ioana    9
Rezultatul funcției: kotlin.Unit

Greșeli frecvente

  • Lipsa tipului la un parametru (fun f(x)): în Kotlin tipul parametrilor este obligatoriu.
  • Uitarea lui return într-o funcție cu acolade care declară un tip: fun f(): Int { 5 } dă eroarea missing return statement. Varianta scurtă este fun f() = 5.
  • Încercarea de a modifica un parametru (pret = pret * 2): parametrii sunt val. Folosește o variabilă locală nouă.

Comenzi înrudite

  • return: Încheie funcția curentă și întoarce o valoare apelantului; cu etichetă (return@forEach) iese doar din lambda.
  • lambda: O lambda este o funcție fără nume, scrisă între acolade, pe care o poți pune într-o variabilă sau trimite altei funcții.
  • vararg: vararg permite unei funcții să primească oricâte argumente de același tip, văzute în corp ca un tablou.
  • Funcții de extensie: O funcție de extensie adaugă o metodă nouă unui tip existent (String, Int, List), fără să modifici clasa.
  • fun main(): Funcția main este punctul de pornire al oricărui program Kotlin: codul din ea se execută primul.