Higher-order function, başka bir fonksiyonu parametre olarak alan veya sonuç olarak bir fonksiyon döndüren fonksiyondur. Kotlin'de fonksiyonlar birinci sınıf vatandaşlardır: değişkenlerde saklanabilir, argüman olarak geçilebilir ve döndürülebilir. Kotlin belgelerine (2026) göre, higher-order functions, bildirimsel yaklaşımlara kıyasla kod tekrarını ortalama %30 azaltır. Higher-order function, modern geliştirmede işlevsel stilin temel bir kavramıdır.
Ana Noktalar
Higher-order function, iki özellikten en az birine sahip olan fonksiyondur: başka bir fonksiyonu argüman olarak almak veya sonuç olarak bir fonksiyon döndürmek. Matematikte, bu tür fonksiyonlara fonksiyonel veya operatör denir. Programlamada, 1958'de Lisp'de ortaya çıktılar ve tüm modern dillerin — JavaScript, Python, Swift, Kotlin, Scala ve Haskell — zorunlu bir parçası haline geldiler. Higher-order function, belirli bir işlemden soyutlamaya ve davranışı değer olarak geçirmeye izin verir.
Higher-order function ile sıradan bir fonksiyon arasındaki temel fark, işlevsel türde bir parametrenin veya döndürülen işlevsel bir değerin varlığıdır. Kotlin'de işlevsel bir tür (ParamType) -> ReturnType olarak yazılır. Örneğin, (Int) -> String türü, Int alan ve String döndüren bir fonksiyon anlamına gelir. () -> Unit türü, parametresiz ve yararlı bir değer döndürmeyen bir fonksiyonu belirtir. Bu tür sistemi, higher-order functions'ı tür güvenli yapar.
Higher-order function'ın zıttı ise first-class functiondır (birinci sınıf fonksiyon). First-class function, bir fonksiyonun diğer herhangi bir değer gibi kullanılabileceği anlamına gelir: bir değişkene atanabilir, bir koleksiyonda saklanabilir, argüman olarak geçilebilir. Higher-order function, almak veya döndürmek için first-class functions kullanan bir fonksiyondur. Kotlin, ek kütüphane olmadan dil düzeyinde her iki kavramı da destekler.
Kotlin'de, en az bir parametresi işlevsel türle bildirilmiş veya dönüş türü işlevsel olan herhangi bir fonksiyon otomatik olarak higher-order function olarak kabul edilir. Derleyici özel bir ek gerektirmez — imzada (T) -> R belirtmek yeterlidir. Böyle bir fonksiyon çağrıldığında, argüman bir lambda ifadesi, :: aracılığıyla mevcut bir fonksiyona referans veya bir değişkende saklanan işlevsel bir değerdir.
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
}
Listelemede, operate fonksiyonu iki tam sayı ve (Int, Int) -> Int türünde bir op parametresi alır. Fonksiyonun gövdesi, iletilen işlemi tek bir satırda çağırır. main'de, operate çağrısı lambda { x, y -> x + y }'yi iletir — Kotlin, trailing lambda sözdizimi sayesinde bunu parantezlerden sonra yerleştirir. Lambda son argüman olsaydı, tamamen parantezlerin dışına taşınabilirdi, bu da çağrı zincirlerinin okunabilirliğini artırır.
Perde arkasında Kotlin, higher-order functions'ı Function arayüzü aracılığıyla derler (iki parametre için Function2). Her lambda, karşılık gelen FunctionN arayüzünü uygulayan anonim bir sınıfa dönüşür. Bu, lambda oluşturmanın her işlem için bir nesne ayırma anlamına geldiği anlamına gelir. Ek yükü azaltmak için Kotlin, inline fonksiyonları destekler ve higher-order function'ın gövdesini çağrı sitesinde değiştirerek anonim sınıf oluşturmayı ortadan kaldırır.
Bir fonksiyonu argüman olarak geçirmek, higher-order functions kullanımının en yaygın modelidir. Polimorfik bir yöntemle sınıf hiyerarşisi oluşturmak yerine, geliştirici istenen davranışı doğrudan kullanım noktasına iletir. Bu, kalıtım olmadan Açık/Kapalı ilkesini uygular: yeni bir işlem yeni bir alt sınıf olarak değil, yeni bir lambda olarak eklenir.
Nullable fonksiyonlar için Kotlin, parantezlerden sonra soru işaretiyle ((T) -> R)? türünü kullanır. Böyle bir fonksiyon yalnızca null kontrolünden sonra veya ?.invoke() operatörü aracılığıyla çağrılabilir. Bu durumda, higher-order function'ın imzası, bir fonksiyon geçirmenin isteğe bağlı olduğunu açıkça belirtir — çağıran kod argümanı atlayabilir. Bu, isteğe bağlı davranışa sahip geri aramalar ve olay işleyicileri için kullanışlı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]
}
Genişletme fonksiyonu customFilter, işlevsel tür (T) -> Boolean olan bir predicate parametresi alır. Döngü içinde, her öğe için predicate'i çağırır ve eşleşenleri toplar. main'deki çağrı, lambda { it % 2 == 0 }'yi iletir; burada it, lambda'nın tek parametresinin örtük adıdır. Higher-order functions sayesinde, filtreleme mantığı koleksiyon tarama mekanizmasından tamamen izole edilmiştir.
Bir higher-order function bir fonksiyon döndürebilir — bu modele fonksiyon fabrikası veya davranış üreteci denir. Döndürülen fonksiyon, dış kapsamdaki değişkenleri yakalayabilir (closure) ve çağrılar arasında koruyabilir. Bu, ortak şablonlara dayalı olarak yapılandırılabilir işleyiciler ve özelleştirilmiş işlemler oluşturmaya izin verir.
Bir fonksiyon döndürürken Kotlin, imzadan döndürülen işlevsel türü ((T) -> R)? çıkarır. Derleyici, gövdedeki tüm return ifadelerinin uyumlu işlevsel değerler döndürdüğünü kontrol eder. Yakalanan değişkenler lambda nesnesinde saklanır ve ona bir referans olduğu sürece erişilebilir kalır. Bu güçlü bir mekanizmadır ancak bellek yönetimine dikkat edilmesini gerektirir.
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 fonksiyonu bir factor alır ve lambda { x -> x * factor } döndürür; burada factor dış kapsamdan (closure) yakalanır. Her makeMultiplier çağrısı, kendi factor değerine sahip yeni bir fonksiyon oluşturur. double ve triple değişkenleri döndürülen fonksiyonları saklar ve birden çok kez çağrılabilir. Bu model, HTTP istemci yapılandırmasında, dekoratörlerde ve middleware'de yaygın olarak kullanılır.
Higher-order functions ve lambdaların birleşimi, ara değişkenler olmadan anlamlı işlem zincirleri oluşturmaya izin verir. Kotlin standart kütüphanesi düzinelerce higher-order function içerir: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy ve diğerleri. Her biri bir lambda alır ve onunla veri dönüşümü gerçekleştirir.
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]
}
Örnekte, üç higher-order function'dan oluşan bir zincir, bir kullanıcı listesini işler. filter bir yüklem alır ve yalnızca yetişkinleri bırakır. map, her kullanıcıyı büyük harfli bir ada dönüştürür. sorted, sonucu artan düzende sıralar. Her işlem bir lambda alır ve Kotlin her aşamada tür güvenliğini sağlar. Higher-order functions olmadan, if ile bir döngü, geçici listeler ve manuel sıralama yazmak gerekirdi.
Sıkça Sorulan Sorular
Higher-order function, başka bir fonksiyonu parametre olarak alır veya bir fonksiyon döndürür. Sıradan bir fonksiyon yalnızca verilerle — sayılar, dizeler, nesneler — çalışır. Higher-order function davranışla çalışır ve mantığı argüman olarak iletir.
Evet, inline değiştiricisi, bir lambda için anonim sınıf oluşturma ek yükünü ortadan kaldırır. crossinline veya noinline kullanarak, hangi lambdaların ekleneceği ve hangilerinin nesne olarak kalacağı kontrol edilebilir.
Parametresiz ve dönüş değeri olmayan bir fonksiyonun türü () -> Unit'tir. T türünde bir parametre ve R dönüşü olan bir fonksiyon (T) -> R olarak yazılır. İki parametre için — (T, U) -> R ve bu şekilde 22 argümana kadar devam eder.
Lambda, kısa bir gösterimdir { args -> body }, anonim fonksiyon ise fun(args): ReturnType { body } şeklindedir. Lambda, etiket olmadan return kullanamaz, anonim fonksiyon kullanabilir. Her ikisi de bir higher-order function'a geçilebilir.
Inline olmadan sıcak döngülerde higher-order functions'dan kaçının — her lambda bir nesne oluşturur. Performans açısından kritik kod için inline fun kullanın. Ayrıca, derin iç içe lambdaları kötüye kullanmayın — bu okunabilirliği azaltır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun