Higher-order function — je funkce, která přijímá jinou funkci jako parametr nebo vrací funkci jako výsledek. V Kotlinu jsou funkce objekty první třídy: lze je ukládat do proměnných, předávat jako argumenty a vracet. Podle dokumentace Kotlinu (2026) snižují higher-order functions duplicitu kódu v průměru o 30% ve srovnání s imperativními přístupy. Higher-order function — základní koncept funkcionálního stylu v moderním vývoji.
Hlavní body
Higher-order function — je funkce, která má alespoň jednu ze dvou vlastností: přijímání jiné funkce jako argumentu nebo vracení funkce jako výsledku. V matematice se takové funkce nazývají funkcionály nebo operátory. V programování se objevily v Lispu v roce 1958 a staly se povinnou součástí všech moderních jazyků — JavaScript, Python, Swift, Kotlin, Scala a Haskell. Higher-order function umožňuje abstrahovat od konkrétní operace a předávat chování jako hodnotu.
Klíčový rozdíl mezi higher-order function a běžnou funkcí — přítomnost parametru s funkcionálním typem nebo vrácené funkcionální hodnoty. V Kotlinu se funkcionální typ zapisuje jako (ParamType) -> ReturnType. Například typ (Int) -> String znamená funkci přijímající Int a vracející String. Typ () -> Unit označuje funkci bez parametrů, která nevrací užitečnou hodnotu. Právě tento typový systém činí higher-order functions typově bezpečnými.
Opakem higher-order function je first-class function (funkce první třídy). First-class function znamená, že funkci lze použít jako jakoukoli jinou hodnotu: přiřadit proměnné, uložit do kolekce, předat jako argument. Higher-order function je funkce, která používá first-class functions k přijímání nebo vracení. Kotlin podporuje oba koncepty na úrovni jazyka bez dalších knihoven.
V Kotlinu je každá funkce, která má alespoň jeden parametr deklarovaný s funkcionálním typem nebo jejíž návratový typ je funkcionální, automaticky považována za higher-order function. Kompilátor nevyžaduje speciální anotaci — stačí uvést (T) -> R v signatuře. Při volání takové funkce se jako argument předá buď lambda výraz, nebo odkaz na existující funkci přes ::, nebo funkcionální hodnota uložená v proměnné.
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
}
Ve výpisu funkce operate přijímá dvě celá čísla a parametr op typu (Int, Int) -> Int. Tělo funkce v jednom řádku volá předanou operaci. V main volání operate předá lambdu { x, y -> x + y } — Kotlin ji umístí za závorky díky syntaxi trailing lambda. Pokud by lambda byla posledním argumentem, mohla by být zcela vyjmuta mimo závorky, což zvyšuje čitelnost řetězců volání.
Pod kapotou Kotlin kompiluje higher-order function přes rozhraní Function (Function2 pro dva parametry). Každá lambda se přemění na anonymní třídu implementující odpovídající rozhraní FunctionN. To znamená, že vytvoření lambdy znamená alokaci objektu pro každou operaci. Pro snížení režie Kotlin podporuje inline funkce, které vkládají tělo higher-order function na místo volání, čímž eliminují vytváření anonymní třídy.
Předávání funkce jako argumentu — nejběžnější vzor použití higher-order function. Místo vytváření hierarchie tříd s polymorfní metodou programátor předá potřebné chování přímo do místa použití. To implementuje princip Otevřenosti/Uzavřenosti (Open/Closed Principle) bez dědičnosti: nová operace se přidá jako nová lambda, nikoli jako nová podtřída.
Pro nullable funkce Kotlin používá typ ((T) -> R)? s otazníkem za závorkami. Takovou funkci lze volat až po kontrole null nebo pomocí operátoru ?.invoke(). Signatura higher-order function jasně ukazuje, že předání funkce není povinné — volající kód může argument vynechat. To je užitečné pro callbacky a obsluhy událostí s volitelným chováním.
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]
}
Rozšiřující funkce customFilter přijímá parametr predicate funkcionálního typu (T) -> Boolean. Uvnitř cyklu volá predicate pro každý prvek a shromažďuje odpovídající. Volání v main předá lambdu { it % 2 == 0 }, kde it je implicitní název jediného parametru lambdy. Díky higher-order function je logika filtrování zcela oddělena od mechanismu procházení kolekce.
Higher-order function může vrátit funkci — takový vzor se nazývá továrna na funkce nebo generátor chování. Vrácená funkce může zachytit (closure) proměnné z vnějšího rozsahu viditelnosti a uchovávat je mezi voláními. To umožňuje vytvářet konfigurovatelné obsluhy a specializované operace na základě obecných šablon.
Při vracení funkce Kotlin odvodí vrácený funkcionální typ ((T) -> R)? ze signatury. Kompilátor kontroluje, že všechny return výrazy v těle vracejí kompatibilní funkcionální hodnoty. Zachycené proměnné jsou uloženy v objektu lambdy a jsou přístupné, dokud existuje odkaz na ni. To je mocný mechanismus, ale vyžaduje pozornost při správě paměti.
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
}
Funkce makeMultiplier přijímá factor a vrací lambdu { x -> x * factor }, kde factor je zachycen z vnějšího rozsahu (closure). Při každém volání makeMultiplier je vytvořena nová funkce s vlastní hodnotou factor. Proměnné double a triple ukládají vrácené funkce a lze je volat opakovaně. Tento vzor je široce používán při konfiguraci HTTP klientů, dekorátorů a middleware.
Kombinované použití higher-order function a lambd umožňuje budovat expresivní řetězce operací bez mezilehlých proměnných. Standardní knihovna Kotlinu obsahuje desítky higher-order functions: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy a další. Každá z nich přijímá lambdu a s její pomocí provádí transformaci dat.
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]
}
V příkladu řetězec tří higher-order functions zpracovává seznam uživatelů. filter přijímá predikát, ponechává pouze plnoleté uživatele. map převádí každého uživatele na jméno velkými písmeny. sorted řadí výsledek vzestupně. Každá operace přijímá lambdu a Kotlin zajišťuje typovou bezpečnost ve všech fázích. Bez higher-order function by bylo nutné napsat cyklus s if, dočasnými seznamy a ručním řazením.
Často kladené otázky
Higher-order function přijímá jinou funkci jako parametr nebo ji vrací. Běžná funkce pracuje pouze s daty — čísly, řetězci, objekty. Higher-order function pracuje s chováním a předává logiku jako argument.
Ano, modifikátor inline odstraňuje režii vytváření anonymní třídy pro lambdu. Pomocí crossinline nebo noinline lze řídit, které lambdy jsou vloženy a které zůstávají objekty.
Funkce bez parametrů a bez návratové hodnoty má typ () -> Unit. Funkce s jedním parametrem typu T a návratem R se zapisuje jako (T) -> R. Pro dva parametry — (T, U) -> R a tak dále až do 22 argumentů.
Lambda — stručný zápis { args -> body }, anonymní funkce — fun(args): ReturnType { body }. Lambda nemůže mít return bez popisku, anonymní funkce může. Obě lze předat do higher-order function.
Vyhněte se higher-order function v horkých smyčkách bez inline — každá lambda vytváří objekt. Pro kritický výkon použijte inline fun. Také nezneužívejte hluboké vnořování lambd — snižuje to čitelnost.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také