Higher-order function — başqa bir funksiyanı parametr kimi qəbul edən və ya nəticə olaraq funksiya qaytaran funksiyadır. Kotlin-də funksiyalar birinci dərəcəli obyektlərdir: onları dəyişənlərdə saxlamaq, arqument kimi ötürmək və qaytarmaq olar. Kotlin sənədlərinə (2026) əsasən, higher-order functions imperativ yanaşmalarla müqayisədə kod təkrarlanmasını orta hesabla 30% azaldır. Higher-order function — müasir inkişafda funksional üslubun əsas konsepsiyasıdır.
Əsas məqamlar
Higher-order function — iki xüsusiyyətdən ən azı birinə malik olan funksiyadır: başqa funksiyanı arqument kimi qəbul etmək və ya nəticə olaraq funksiya qaytarmaq. Riyaziyyatda belə funksiyalar funksional və ya operator adlanır. Proqramlaşdırmada onlar 1958-ci ildə Lisp-də meydana çıxdı və bütün müasir dillərin — JavaScript, Python, Swift, Kotlin, Scala və Haskell-in məcburi hissəsinə çevrildi. Higher-order function konkret əməliyyatdan abstraksiya etməyə və davranışı dəyər kimi ötürməyə imkan verir.
Higher-order function ilə adi funksiya arasındakı əsas fərq — funksional tipli parametrin və ya qaytarılan funksional dəyərin olmasıdır. Kotlin-də funksional tip (ParamType) -> ReturnType kimi yazılır. Məsələn, (Int) -> String tipi Int qəbul edən və String qaytaran funksiyanı bildirir. () -> Unit tipi parametrsiz, faydalı dəyər qaytarmayan funksiyanı bildirir. Məhz bu tip sistemi higher-order function-ları tip-təhlükəsiz edir.
Higher-order function-un əksi — first-class function (birinci dərəcəli funksiya). First-class function o deməkdir ki, funksiya hər hansı digər dəyər kimi istifadə oluna bilər: dəyişənə təyin etmək, kolleksiyada saxlamaq, arqument kimi ötürmək. Higher-order function — first-class functions-dan qəbul və ya qaytarma üçün istifadə edən funksiyadır. Kotlin hər iki konsepsiyanı dil səviyyəsində əlavə kitabxanalar olmadan dəstəkləyir.
Kotlin-də funksional tipli ən azı bir parametri olan və ya qaytarılan tipi funksional olan hər bir funksiya avtomatik olaraq higher-order function sayılır. Kompilyator xüsusi annotasiya tələb etmir — imzada (T) -> R göstərmək kifayətdir. Belə funksiyanı çağırdıqda arqument olaraq ya lambda ifadəsi, ya :: vasitəsilə mövcud funksiyaya istinad, ya da dəyişəndə saxlanılan funksional dəyər ötürülü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
}
Nümunədə operate funksiyası iki tam ədəd və (Int, Int) -> Int tipli op parametrini qəbul edir. Funksiyanın gövdəsi bir sətirdə ötürülən əməliyyatı çağırır. main-də operate çağırışı { x, y -> x + y } lambdasını ötürür — Kotlin trailing lambda sintaksisi sayəsində onu mötərizələrdən sonra yerləşdirir. Lambda son arqument olsaydı, onu tamamilə mötərizələrdən kənara çıxarmaq olardı ki, bu da çağırış zəncirlərinin oxunaqlılığını artırır.
Daxildə Kotlin higher-order function-u Function interfeysi (iki parametr üçün Function2) vasitəsilə kompilə edir. Hər bir lambda müvafiq FunctionN interfeysini tətbiq edən anonim sinfə çevrilir. Bu o deməkdir ki, lambda yaratmaq hər əməliyyat üçün obyekt ayırmasına səbəb olur. Yükü azaltmaq üçün Kotlin inline funksiyalarını dəstəkləyir, onlar higher-order function-un gövdəsini çağırış yerinə yerləşdirərək anonim sinif yaradılmasını aradan qaldırır.
Funksiyanı arqument kimi ötürmək — higher-order function-dan istifadənin ən çox yayılmış nümunəsidir. Təbəqə iyerarxiyası yaratmaq əvəzinə, proqramçı lazımi davranışı birbaşa istifadə nöqtəsinə ötürür. Bu, vərəsəlik olmadan Açıq/Qapalı Prinsipini (Open/Closed Principle) tətbiq edir: yeni əməliyyat yeni alt sinif kimi deyil, yeni lambda kimi əlavə olunur.
Nullable funksiyalar üçün Kotlin mötərizələrdən sonra sual işarəsi ilə ((T) -> R)? tipindən istifadə edir. Belə funksiyanı yalnız null yoxlamasından sonra və ya ?.invoke() operatoru vasitəsilə çağırmaq olar. Higher-order function imzası açıq şəkildə göstərir ki, funksiyanın ötürülməsi məcburi deyil — çağıran kod arqumenti buraxa bilər. Bu, seçimlik davranışı olan callback və hadisə işləyiciləri üçün faydalıdır.
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 genişləndirmə funksiyası (T) -> Boolean funksional tipində predicate parametrini qəbul edir. Dövrə daxilində hər element üçün predicate çağırır və uyğun olanları toplayır. main-də çağırış { it % 2 == 0 } lambdasını ötürür, burada it lambda-nın yeganə parametrinin gizli adıdır. Higher-order function sayəsində filtrləmə məntiqi kolleksiyanı gəzmə mexanizmindən tamamilə ayrılmışdır.
Higher-order function funksiya qaytara bilər — belə nümunə funksiya fabriki və ya davranış generatoru adlanır. Qaytarılan funksiya xarici görünmə sahəsindən dəyişənləri (closure) ələ keçirə və onları çağırışlar arasında saxlaya bilər. Bu, ümumi şablonlar əsasında konfiqurasiya olunan işləyicilər və ixtisaslaşdırılmış əməliyyatlar yaratmağa imkan verir.
Funksiya qaytararkən Kotlin imzadan qaytarılan funksional tipi ((T) -> R)? çıxarır. Kompilyator gövdədəki bütün return ifadələrinin uyğun funksional dəyərlər qaytardığını yoxlayır. Ələ keçirilən dəyişənlər lambda obyektində saxlanılır və ona istinad mövcud olduğu müddətcə əlçatandır. Bu güclü mexanizmdir, lakin yaddaşın idarə edilməsinə diqqət tələb edir.
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 funksiyası factor qəbul edir və { x -> x * factor } lambdasını qaytarır, burada factor xarici sahədən (closure) ələ keçirilir. Hər makeMultiplier çağırışında öz factor dəyəri olan yeni funksiya yaradılır. double və triple dəyişənləri qaytarılmış funksiyaları saxlayır və dəfələrlə çağırıla bilər. Bu nümunə HTTP müştərilərinin konfiqurasiyasında, dekoratorlarda və middleware-də geniş istifadə olunur.
Higher-order function və lambdaların birgə istifadəsi aralıq dəyişənlər olmadan ifadəli əməliyyat zəncirləri qurmağa imkan verir. Kotlin-in standart kitabxanasında onlarla higher-order functions var: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy və s. Onların hər biri lambda qəbul edir və onun köməyi ilə məlumat çevrilməsi həyata keçirir.
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ümunədə üç higher-order functions zənciri istifadəçi siyahısını emal edir. filter predikat qəbul edir, yalnız yetkin istifadəçiləri saxlayır. map hər istifadəçini böyük hərflərlə yazılmış ada çevirir. sorted nəticəni artan sıra ilə çeşidləyir. Hər əməliyyat lambda qəbul edir və Kotlin bütün mərhələlərdə tip təhlükəsizliyini təmin edir. Higher-order function olmadan if, müvəqqəti siyahılar və əl ilə çeşidləmə ilə dövrə yazmaq lazım gələrdi.
Tez-tez verilən suallar
Higher-order function başqa funksiyanı parametr kimi qəbul edir və ya onu qaytarır. Adi funksiya yalnız məlumatlarla — ədədlər, sətirlər, obyektlərlə işləyir. Higher-order function davranışla işləyir, məntiqi arqument kimi ötürür.
Bəli, inline modifikatoru lambda üçün anonim sinif yaradılması ilə bağlı yükü aradan qaldırır. crossinline və ya noinline istifadə edərək hansı lambdaların yerləşdirilməsini, hansıların obyekt olaraq qalmasını idarə etmək olar.
Parametrsiz və qaytarılan dəyəri olmayan funksiya () -> Unit tiplinə malikdir. T tipində bir parametri olan və R qaytaran funksiya (T) -> R kimi yazılır. İki parametr üçün — (T, U) -> R və 22 arqumentə qədər belə davam edir.
Lambda — { args -> body } qısa qeydidir, anonim funksiya — fun(args): ReturnType { body }. Lambda etiketsiz return edə bilməz, anonim funksiya edə bilər. Hər ikisi higher-order function-a ötürülə bilər.
Inlinesiz isti dövrələrdə higher-order function-dan qaçının — hər lambda obyekt yaradır. Kritik performans üçün inline fun istifadə edin. Həmçinin lambdaların dərin yerləşdirilməsindən sui-istifadə etməyin — bu oxunaqlılığı azaldır.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun