Higher-order function — este o funcție care primește o altă funcție ca parametru sau returnează o funcție ca rezultat. În Kotlin, funcțiile sunt obiecte de primă clasă: pot fi stocate în variabile, transmise ca argumente și returnate. Conform documentației Kotlin (2026), higher-order functions reduc duplicarea codului în medie cu 30% comparativ cu abordările imperative. Higher-order function — concept fundamental al stilului funcțional în dezvoltarea modernă.
Principalele puncte
Higher-order function — este o funcție care posedă cel puțin una dintre cele două caracteristici: primirea unei alte funcții ca argument sau returnarea unei funcții ca rezultat. În matematică, astfel de funcții se numesc funcționale sau operatori. În programare, au apărut în Lisp în 1958 și au devenit o parte obligatorie a tuturor limbajelor moderne — JavaScript, Python, Swift, Kotlin, Scala și Haskell. Higher-order function permite abstractizarea de la o operație specifică și transmiterea comportamentului ca valoare.
Diferența cheie între higher-order function și o funcție obișnuită — prezența unui parametru cu tip funcțional sau a unei valori funcționale returnate. În Kotlin, tipul funcțional se scrie ca (ParamType) -> ReturnType. De exemplu, tipul (Int) -> String înseamnă o funcție care primește Int și returnează String. Tipul () -> Unit denotă o funcție fără parametri, care nu returnează o valoare utilă. Tocmai acest sistem de tipuri face higher-order functions sigure din punct de vedere al tipurilor.
Opusul higher-order function — first-class function (funcție de primă clasă). First-class function înseamnă că o funcție poate fi folosită ca orice altă valoare: atribuită unei variabile, stocată într-o colecție, transmisă ca argument. Higher-order function — este o funcție care folosește first-class functions pentru a primi sau returna. Kotlin suportă ambele concepte la nivel de limbaj fără biblioteci suplimentare.
În Kotlin, orice funcție care are cel puțin un parametru declarat cu tip funcțional sau tipul returnat este funcțional, este considerată automat higher-order function. Compilatorul nu necesită o adnotare specială — este suficient să specificați (T) -> R în semnătură. La apelarea unei astfel de funcții, ca argument se transmite fie o expresie lambda, fie o referință la o funcție existentă prin ::, fie o valoare funcțională stocată într-o variabilă.
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int {
return op(a, b)
}
fun main() {
val sum = operate(10, 20) { x, y -> x + y }
println(sum) // 30
}
În listare, funcția operate primește două numere întregi și parametrul op de tipul (Int, Int) -> Int. Corpul funcției într-o singură linie apelează operația transmisă. În main, apelul operate transmite lambda { x, y -> x + y } — Kotlin o plasează după paranteze datorită sintaxei trailing lambda. Dacă lambda ar fi ultimul argument, ar putea fi scoasă complet în afara parantezelor, ceea ce crește lizibilitatea lanțurilor de apeluri.
Sub capotă, Kotlin compilează higher-order function prin interfața Function (Function2 pentru doi parametri). Fiecare lambda se transformă într-o clasă anonimă care implementează interfața FunctionN corespunzătoare. Aceasta înseamnă că crearea unei lambde implică alocarea unui obiect pentru fiecare operație. Pentru a reduce suprasarcina, Kotlin suportă funcțiile inline, care inserează corpul higher-order function la locul apelului, eliminând crearea clasei anonime.
Transmiterea unei funcții ca argument — cel mai frecvent model de utilizare a higher-order function. În loc să creați o ierarhie de clase cu o metodă polimorfică, programatorul transmite comportamentul necesar direct în punctul de utilizare. Aceasta implementează principiul „deschis pentru extensie” (Open/Closed Principle) fără moștenire: o nouă operație se adaugă ca o nouă lambda, nu ca o nouă subclasă.
Pentru funcțiile nullable, Kotlin folosește tipul ((T) -> R)? cu semnul întrebării după paranteze. O astfel de funcție poate fi apelată doar după verificarea null sau prin operatorul ?.invoke(). Semnătura higher-order function indică clar că transmiterea funcției nu este obligatorie — codul apelant poate omite argumentul. Acest lucru este util pentru callback-uri și handler-e de evenimente cu comportament opțional.
fun <T> List<T>.customFilter(
predicate: (T) -> Boolean
): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (predicate(item)) result.add(item)
}
return result
}
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
val even = numbers.customFilter { it % 2 == 0 }
println(even) // [2, 4]
}
Funcția de extensie customFilter primește parametrul predicate de tipul funcțional (T) -> Boolean. În interiorul buclei, apelează predicate pentru fiecare element și colectează pe cele potrivite. Apelul în main transmite lambda { it % 2 == 0 }, unde it este numele implicit al unicului parametru al lambdei. Datorită higher-order function, logica de filtrare este complet separată de mecanismul de parcurgere a colecției.
Higher-order function poate returna o funcție — un astfel de model se numește fabrică de funcții sau generator de comportament. Funcția returnată poate captura (closure) variabile din domeniul de vizibilitate extern, păstrându-le între apeluri. Acest lucru permite crearea de handler-e configurabile și operații specializate pe baza unor șabloane generale.
La returnarea unei funcții, Kotlin inferă tipul funcțional returnat ((T) -> R)? din semnătură. Compilatorul verifică că toate expresiile return din corp returnează valori funcționale compatibile. Variabilele capturate sunt stocate în obiectul lambdei și sunt accesibile atâta timp cât există o referință la ea. Acesta este un mecanism puternic, dar care necesită atenție la gestionarea memoriei.
fun makeMultiplier(factor: Int): (Int) -> Int {
return { x -> x * factor }
}
fun main() {
val double = makeMultiplier(2)
val triple = makeMultiplier(3)
println(double(5)) // 10
println(triple(5)) // 15
}
Funcția makeMultiplier primește factor și returnează lambda { x -> x * factor }, unde factor este capturat din domeniul extern (closure). La fiecare apel al makeMultiplier, se creează o nouă funcție cu propria valoare factor. Variabilele double și triple stochează funcțiile returnate și pot fi apelate de mai multe ori. Acest model este utilizat pe scară largă în configurarea clienților HTTP, decoratorilor și middleware-ului.
Utilizarea combinată a higher-order function și a lambdelor permite construirea de lanțuri de operații expresive fără variabile intermediare. Biblioteca standard Kotlin conține zeci de higher-order functions: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy și altele. Fiecare dintre ele primește o lambda și efectuează cu ajutorul ei transformarea datelor.
data class User(val name: String, val age: Int)
fun main() {
val users = listOf(
User("Alice", 25),
User("Bob", 17),
User("Charlie", 30)
)
val result = users
.filter { it.age >= 18 }
.map { it.name.uppercase() }
.sorted()
println(result) // [ALICE, CHARLIE]
}
În exemplu, un lanț de trei higher-order functions procesează o listă de utilizatori. filter primește un predicat, păstrând doar utilizatorii majori. map transformă fiecare utilizator într-un nume scris cu majuscule. sorted sortează rezultatul crescător. Fiecare operație primește o lambda, iar Kotlin asigură siguranța tipurilor în toate etapele. Fără higher-order function, ar trebui scrisă o buclă cu if, liste temporare și sortare manuală.
Întrebări frecvente
Higher-order function primește o altă funcție ca parametru sau o returnează. O funcție obișnuită lucrează doar cu date — numere, șiruri, obiecte. Higher-order function lucrează cu comportament, transmițând logica ca argument.
Da, modificatorul inline elimină suprasarcina creării unei clase anonime pentru lambda. Folosind crossinline sau noinline, se poate gestiona care lambde sunt inserate și care rămân obiecte.
O funcție fără parametri și fără valoare returnată are tipul () -> Unit. O funcție cu un parametru de tip T și returnarea R se scrie ca (T) -> R. Pentru doi parametri — (T, U) -> R și așa mai departe până la 22 de argumente.
Lambda — notație compactă { args -> body }, funcția anonimă — fun(args): ReturnType { body }. Lambda nu poate avea return fără etichetă, funcția anonimă poate. Ambele pot fi transmise către higher-order function.
Evitați higher-order function în buclele fierbinți fără inline — fiecare lambda creează un obiect. Pentru performanță critică, folosiți inline fun. De asemenea, nu abuzați de imbricarea profundă a lambdelor — aceasta reduce lizibilitatea.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și