Higher-order function sangat berguna, tetapi setiap lambda yang kita teruskan sebagai argumen sebenarnya dikompilasi menjadi instance class anonim. Bila function dipanggil jutaan kali dalam loop ketat, biaya alokasi tersebut menjadi signifikan. Kotlin menyediakan keyword inline yang memberi tahu kompilator untuk menyalin body function ke setiap call site. Pada chapter ini kita akan melihat bagaimana inline bekerja dan kapan perlu dipakai.

Deklarasi inline Function #

Keyword inline diletakkan sebelum fun. Kompilator akan menyalin body function (termasuk body lambda yang diteruskan sebagai argumen) ke lokasi pemanggilan. Hasilnya adalah bytecode yang lebih besar tetapi tanpa alokasi objek lambda.

kotlin
inline fun ulangi(kali: Int, blok: (Int) -> Unit) {
    for (i in 1..kali) {
        blok(i)
    }
}

inline fun konfirmasi(pesan: String, blok: () -> Boolean): String {
    return if (blok()) "BERHASIL: $pesan" else "GAGAL: $pesan"
}

inline fun transformasi(daftar: List<Int>, blok: (Int) -> Int): List<Int> {
    val hasil = mutableListOf<Int>()
    for (n in daftar) {
        hasil.add(blok(n))
    }
    return hasil
}

fun main() {
    ulangi(3) { i ->
        println("Iterasi ke-$i")
    }

    val status = konfirmasi("validasi data") { 5 > 3 }
    println(status)

    val data = listOf(1, 2, 3, 4, 5)
    val dikuadrat = transformasi(data) { it * it }
    println("Dikuadrat: $dikuadrat")
}

Output yang Dihasilkan:

text
Iterasi ke-1
Iterasi ke-2
Iterasi ke-3
BERHASIL: validasi data
Dikuadrat: [1, 4, 9, 16, 25]

Mari kita bedah baris per baris:

  1. inline fun ulangi(kali: Int, blok: (Int) -> Unit): keyword inline menandai function. Saat dipanggil, body function disalin ke call site — loop for (i in 1..kali) dan body lambda blok(i) digabungkan menjadi satu kesatuan kode tanpa alokasi lambda.
  2. ulangi(3) { i -> println("Iterasi ke-$i") }: lambda { i -> ... } tidak dijadikan instance class, melainkan disalin sebagai blok kode langsung di call site.
  3. inline fun konfirmasi(pesan: String, blok: () -> Boolean): String: lambda () -> Boolean di-inline sehingga pemanggilan blok() diganti dengan ekspresi 5 > 3 langsung.
  4. inline fun transformasi(...): lambda it * it disalin ke dalam loop for, sehingga tidak ada alokasi lambda per elemen daftar.

Manfaat dan Biaya #

inline memberi dua manfaat utama:

  • Tanpa alokasi lambda: kompilator tidak membuat instance class anonim untuk lambda yang diteruskan
  • Non-local return: lambda inline dapat memakai return untuk keluar dari function induk, tidak mungkin tanpa inline

Namun inline juga punya biaya:

  • Bytecode membengkak: bila function dipanggil di banyak tempat, body disalin ke setiap call site, sehingga ukuran file class bertambah
  • Tidak semua function cocok: function yang sangat panjang atau dipanggil dari banyak lokasi dapat membuat ukuran binary membengkak tanpa manfaat performa yang berarti

Sebagai panduan, inline paling tepat untuk higher-order function kecil yang menerima lambda dan dipanggil dalam loop ketat. Standard library Kotlin memakai inline pada function seperti forEach, map, filter, fold, dan let.

Non-local Return #

Karena body lambda disalin ke call site, return di dalam lambda inline akan keluar dari function induk — bukan hanya dari lambda. Perilaku ini disebut non-local return dan berguna untuk pola early-exit dari loop.

kotlin Contoh: non-local return pada inline lambda
inline fun findFirst(daftar: List<Int>, predikat: (Int) -> Boolean): Int {
    for ((index, n) in daftar.withIndex()) {
        if (predikat(n)) return index
    }
    return -1
}

fun main() {
    val data = listOf(3, 5, 7, 8, 10)
    val idx = findFirst(data) {
        if (it % 2 == 0) return@findFirst true
        false
    }
    println("Indeks elemen genap pertama: $idx")
}

Tanpa inline, pernyataan return@findFirst tidak akan keluar dari function findFirst — hanya dari lambda. Dengan inline, lambda dapat memengaruhi alur function induk secara langsung.

Kapan Tidak Memakai inline #

inline tidak menguntungkan pada beberapa kasus:

  • function tidak menerima parameter bertipe function — tidak ada lambda untuk di-inline
  • function dipanggil dari banyak tempat dengan body panjang — ukuran bytecode bertambah signifikan tanpa manfaat alokasi
  • function dipanggil secara rekursif — kompilator tidak akan meng-inline panggilan rekursif

Referensi Lanjutan #

Ringkasan #

Keyword inline menyalin body higher-order function beserta lambda argumennya ke setiap call site. Manfaat utama adalah hilangnya alokasi objek lambda dan kemampuan non-local return. Biayanya adalah ukuran bytecode yang membengkak bila function dipakai di banyak tempat. Pada chapter noinline dan crossinline berikutnya, kita akan melihat dua modifier tambahan yang memberi kontrol lebih halus terhadap perilaku inline.