Skip to main content

Inline Function

Inline Function adalah fitur Kotlin yang digunakan untuk mengoptimalkan penggunaan Higher-Order Function.

Higher-Order Function memungkinkan kita mengirimkan function atau lambda sebagai parameter. Fitur ini sangat berguna, tetapi pada kondisi tertentu dapat menimbulkan overhead karena lambda dapat direpresentasikan sebagai object pada saat runtime.

Kotlin menyediakan keyword:

inline

untuk memungkinkan compiler melakukan inline optimization.

Masalah pada Higher-Order Function

Contoh Higher-Order Function biasa:

fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Function tersebut menerima lambda:

name: () -> String

Kemudian kita dapat memanggilnya:

println(hello { "Ucup" })
println(hello { "Budi" })

Secara konsep, setiap lambda yang digunakan sebagai argument dapat melibatkan object function pada runtime.

Jika penggunaan Higher-Order Function sangat banyak, overhead tersebut dapat menjadi lebih signifikan.

Menggunakan Inline Function

Kotlin menyediakan keyword inline untuk function yang menggunakan Higher-Order Function.

Contoh:

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Perhatikan keyword:

inline

yang ditambahkan sebelum fun.

Dengan inline, compiler dapat melakukan optimasi dengan memasukkan kode lambda dan function ke lokasi pemanggilnya ketika memungkinkan.

Contoh Pemanggilan Inline Function

Contoh lengkap:

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

fun main() {
println(hello { "Ucup" })
println(hello { "Budi" })
println(hello { "Angga" })
}

Output:

Hello Ucup
Hello Budi
Hello Angga

Lambda:

{ "Ucup" }

dikirim sebagai parameter ke function hello().

Konsep Inline

Secara sederhana, tanpa inline kita dapat membayangkan kode:

println(hello { "Ucup" })

memanggil:

hello(lambda)

Dengan inline, compiler dapat mengoptimalkan kode tersebut dengan konsep seperti memasukkan isi function dan lambda langsung ke lokasi pemanggilan.

Secara konseptual, kurang lebih menjadi:

println("Hello ${"Ucup"}")

Ini adalah gambaran konsep optimasinya, bukan berarti source code asli Anda akan benar-benar diubah seperti contoh tersebut.

Tujuannya adalah mengurangi overhead pemanggilan Higher-Order Function dan pembuatan object lambda pada runtime ketika optimasi inline dapat diterapkan.

Inline Function pada Higher-Order Function

Inline Function paling sering digunakan pada function yang menerima lambda sebagai parameter.

Contoh:

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Parameter:

name: () -> String

merupakan function type.

Karena function hello() menggunakan Higher-Order Function, kita dapat menggunakan inline.

Contoh dengan Beberapa Lambda

Sebuah Inline Function dapat memiliki lebih dari satu parameter lambda.

Contoh:

inline fun hello(
firstName: () -> String,
lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

Pemanggilan:

println(
hello(
{ "Ucup" },
{ "Topekox" }
)
)

Output:

Hello Ucup Topekox

noinline

Ketika sebuah function ditandai dengan:

inline

parameter lambda pada function tersebut secara default akan ikut diperlakukan sebagai inline parameter.

Namun, terkadang kita ingin sebagian lambda tidak di-inline.

Untuk kondisi tersebut, Kotlin menyediakan keyword:

noinline

Contoh noinline

Contoh:

inline fun hello2(
firstName: () -> String,
noinline lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

Pada function tersebut terdapat dua parameter lambda:

firstName: () -> String

dan:

noinline lastName: () -> String

firstName akan diperlakukan sebagai inline parameter.

Sedangkan:

noinline lastName

tidak akan di-inline.

Menggunakan noinline

Contoh pemanggilan:

println(
hello2(
{ "Ucup" },
{ "Topekox" }
)
)

Output:

Hello Ucup Topekox

Contoh lainnya:

println(
hello2(
{ "Budi" },
{ "Santoso" }
)
)

Output:

Hello Budi Santoso

Mengapa Menggunakan noinline?

noinline digunakan ketika kita ingin mempertahankan lambda sebagai object/function value.

Misalnya ketika lambda perlu digunakan sebagai sebuah value atau diteruskan ke proses lain yang membutuhkan function object.

Contoh sederhana:

inline fun process(
action: () -> Unit,
noinline callback: () -> Unit
) {
action()
callback()
}

action akan di-inline, sedangkan callback tidak.

Contoh Program Lengkap

Berikut contoh Inline Function dan noinline:

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

inline fun hello2(
firstName: () -> String,
noinline lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

fun main() {

println(hello { "Ucup" })
println(hello { "Budi" })
println(hello { "Angga" })

println(
hello2(
{ "Ucup" },
{ "Topekox" }
)
)
}

Output:

Hello Ucup
Hello Budi
Hello Angga
Hello Ucup Topekox

Contoh Penggunaan Berulang

Pada contoh berikut, function hello2() dipanggil berulang kali:

for (i in 0..100) {
println(
hello2(
{ "Ucup" },
{ "Topekox" }
)
)
}

Function hello2() menggunakan:

inline fun hello2(
firstName: () -> String,
noinline lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

Parameter firstName di-inline, sedangkan lastName menggunakan noinline.

Inline dan Ukuran Kode

Inline Function bukan berarti selalu lebih baik.

Ketika sebuah function di-inline, kode function dan lambda dapat disalin ke lokasi pemanggilnya.

Jika function berukuran sangat besar dan dipanggil di banyak tempat, inline dapat menyebabkan ukuran bytecode menjadi lebih besar.

Karena itu, inline sebaiknya digunakan pada kondisi yang memang sesuai, terutama untuk Higher-Order Function yang sederhana.

Kapan Menggunakan Inline Function?

Inline Function cocok digunakan ketika:

  • Function menerima lambda sebagai parameter.
  • Higher-Order Function digunakan cukup sering.
  • Lambda yang digunakan relatif kecil.
  • Kita ingin mengurangi overhead function object dan pemanggilan lambda.
  • Kita membutuhkan fitur khusus yang hanya tersedia pada inline function, seperti beberapa penggunaan reified type parameter.

Contoh sederhana:

inline fun execute(action: () -> Unit) {
action()
}

Pemanggilan:

execute {
println("Hello World")
}

Kapan Tidak Perlu Menggunakan Inline?

Tidak semua function harus diberi inline.

Contoh function biasa:

fun sayHello(name: String): String {
return "Hello $name"
}

Function tersebut tidak menggunakan lambda sebagai parameter sehingga tidak ada alasan umum untuk membuatnya inline hanya demi optimasi Higher-Order Function.

Selain itu, inline function yang terlalu besar dapat membuat ukuran bytecode bertambah karena kode dapat disalin ke banyak lokasi pemanggilan.

Perbandingan Function Biasa dan Inline Function

Function Biasa

fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Inline Function

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Perbedaannya hanya pada keyword:

inline

Namun keyword tersebut memberikan instruksi kepada compiler untuk mencoba melakukan inline terhadap function tersebut sesuai aturan dan batasan Kotlin/JVM.

inline dan noinline

Perhatikan contoh berikut:

inline fun hello2(
firstName: () -> String,
noinline lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

Dapat dipahami sebagai:

hello2()

├── firstName
│ └── inline

└── lastName
└── noinline

firstName merupakan parameter lambda yang di-inline.

lastName secara eksplisit diberi noinline, sehingga tidak di-inline.

Kesimpulan

Inline Function adalah fitur Kotlin yang memungkinkan compiler melakukan inline terhadap function, terutama untuk mengoptimalkan penggunaan Higher-Order Function.

Contoh:

inline fun hello(name: () -> String): String {
return "Hello ${name()}"
}

Pemanggilan:

println(hello { "Ucup" })

Inline dapat membantu mengurangi overhead yang berkaitan dengan penggunaan lambda dan Higher-Order Function pada kondisi yang sesuai.

Jika sebuah Inline Function memiliki beberapa parameter lambda dan kita ingin salah satunya tidak di-inline, kita dapat menggunakan:

noinline

Contoh:

inline fun hello2(
firstName: () -> String,
noinline lastName: () -> String
): String {
return "Hello ${firstName()} ${lastName()}"
}

Jadi, konsep utamanya:

tip

inline digunakan untuk memungkinkan compiler memasukkan implementasi function dan lambda ke lokasi pemanggilan ketika memungkinkan, sedangkan noinline digunakan untuk mencegah parameter lambda tertentu agar tidak di-inline.

Perlu diingat bahwa inline adalah optimasi compiler, bukan jaminan bahwa source code atau bytecode akan selalu memiliki bentuk tertentu. Compiler tetap menentukan bagaimana optimasi tersebut diterapkan.