Higher-order function — функција која прима другу функцију као параметар или враћа функцију као резултат. У Kotlin-у функције су објекти прве класе: могу се чувати у променљивама, прослеђивати као аргументи и враћати. Према документацији Kotlin (2026), higher-order functions смањују дуплирање кода у просеку за 30% у поређењу са императивним приступима. Higher-order function — фундаментални концепт функционалног стила у модерном развоју.
Главно
Higher-order function — функција која поседује барем једну од две карактеристике: примање друге функције као аргумента или враћање функције као резултата. У математици се такве функције називају функционалима или операторима. У програмирању су се појавиле у Lisp-у 1958. године и постале обавезан део свих савремених језика — JavaScript, Python, Swift, Kotlin, Scala и Haskell. Higher-order function омогућава апстраховање од конкретне операције и пренос понашања као вредности.
Кључна разлика између higher-order function и обичне функције — присуство параметра са функционалним типом или повратне функционалне вредности. У Kotlin-у се функционални тип записује као (ParamType) -> ReturnType. На пример, тип (Int) -> String означава функцију која прима Int и враћа String. Тип () -> Unit означава функцију без параметара која не враћа корисну вредност. Управо овај систем типова чини higher-order function типски безбедним.
Супротност higher-order function — first-class function (функција прве класе). First-class function значи да се функција може користити као било која друга вредност: доделити променљивој, чувати у колекцији, проследити као аргумент. Higher-order function је функција која користи first-class functions за примање или враћање. Kotlin подржава оба концепта на нивоу језика без додатних библиотека.
У Kotlin-у свака функција која има барем један параметар декларисан са функционалним типом или јој је повратни тип функционалан, аутоматски се сматра higher-order function. Компилатор не захтева посебну анотацију — довољно је навести (T) -> R у потпису. При позиву такве функције, аргументом се прослеђује или ламбда израз, или референца на постојећу функцију преко ::, или функционална вредност сачувана у променљивој.
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
}
У листингу функција operate прима два цела броја и параметар op типа (Int, Int) -> Int. Тело функције у једном реду позива прослеђену операцију. У main позив operate прослеђује ламбду { x, y -> x + y } — Kotlin је смешта после заграда захваљујући trailing lambda синтакси. Да је ламбда била последњи аргумент, могла би се у потпуности извући ван заграда, што повећава читљивост ланаца позива.
Испод хаубе, Kotlin компајлира higher-order function преко интерфејса Function (Function2 за два параметра). Свака ламбда се претвара у анонимну класу која имплементира одговарајући FunctionN интерфејс. То значи да креирање ламбде повлачи алокацију објекта за сваку операцију. Да би се смањио трошак, Kotlin подржава inline функције које убацују тело higher-order function на место позива, елиминишући креирање анонимне класе.
Прослеђивање функције као аргумента — најчешћи образац употребе higher-order function. Уместо креирања хијерархије класа са полиморфном методом, програмер прослеђује потребно понашање директно на место употребе. Ово имплементира принцип „отворености за проширење" (Open/Closed Principle) без наслеђивања: нова операција се додаје као нова ламбда, а не као нова подкласа.
За nullable функције Kotlin користи тип ((T) -> R)? са знаком питања после заграда. Таква функција се може позвати тек након null провере или преко оператора ?.invoke(). Потпис higher-order function јасно указује да прослеђивање функције није обавезно — позивајући код може изоставити аргумент. Ово је корисно за callback-ове и руковаоце догађајима са опционим понашањем.
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]
}
Функција-проширење customFilter прима параметар predicate функционалног типа (T) -> Boolean. Унутар петље позива predicate за сваки елемент и прикупља одговарајуће. Позив у main прослеђује ламбду { it % 2 == 0 }, где је it имплицитно име јединог параметра ламбде. Захваљујући higher-order function логика филтрирања је потпуно одвојена од механизма обиласка колекције.
Higher-order function може вратити функцију — такав образац се назива фабриком функција или генератором понашања. Враћена функција може захватити (closure) променљиве из спољашњег опсега видљивости, чувајући их између позива. Ово омогућава креирање конфигурабилних руковаоца и специјализованих операција на основу општих шаблона.
При враћању функције Kotlin закључује повратни функционални тип ((T) -> R)? из потписа. Компилатор проверава да сви return изрази у телу враћају компатибилне функционалне вредности. Захваћене променљиве се чувају у објекту ламбде и доступне су док постоји референца на њу. Ово је моћан механизам, али захтева пажњу при управљању меморијом.
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
}
Функција makeMultiplier прима factor и враћа ламбду { x -> x * factor }, где је factor захваћен из спољашњег опсега (closure). При сваком позиву makeMultiplier креира се нова функција са сопственом вредношћу factor. Променљиве double и triple чувају враћене функције и могу се позивати више пута. Овај образац се широко примењује у конфигурацији HTTP клијената, декоратора и middleware-а.
Комбиновано коришћење higher-order function и ламбди омогућава изградњу изражајних ланаца операција без међупроменљивих. Стандардна библиотека Kotlin садржи десетине higher-order functions: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy и друге. Свака од њих прима ламбду и уз њену помоћ врши трансформацију података.
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]
}
У примеру ланац од три higher-order functions обрађује листу корисника. filter прима предикат, остављајући само пунолетне. map претвара сваког корисника у име написано великим словима. sorted сортира резултат растуће. Свака операција прима ламбду, а Kotlin обезбеђује типску безбедност у свим фазама. Без higher-order function морао би се написати циклус са if, привременим листама и ручним сортирањем.
Често постављана питања
Higher-order function прима другу функцију као параметар или је враћа. Обична функција ради само са подацима — бројевима, стринговима, објектима. Higher-order function ради са понашањем, прослеђујући логику као аргумент.
Да, inline модификатор елиминише трошак креирања анонимне класе за ламбду. Коришћењем crossinline или noinline може се управљати које ламбде се убацују, а које остају објекти.
Функција без параметара и без повратне вредности има тип () -> Unit. Функција са једним параметром типа T и повратком R записује се као (T) -> R. За два параметра — (T, U) -> R и тако даље до 22 аргумента.
Ламбда — кратак запис { args -> body }, анонимна функција — fun(args): ReturnType { body }. Ламбда не може имати return без ознаке, анонимна функција може. Обе се могу проследити у higher-order function.
Избегавајте higher-order function у врућим петљама без inline — свака ламбда креира објекат. За критичне перформансе користите inline fun. Такође не злоупотребљавајте дубоко угнежђавање ламбди — то смањује читљивост.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође