run adalah scope function yang menggunakan this sebagai receiver dan mengembalikan hasil block sebagai nilai kembalian. Berbeda dari let yang memakai it, run membuat kode di dalam block terbaca seperti method class — panggilan member tanpa prefix. Pada chapter ini kita akan melihat empat pola run — eksekusi block dengan konfigurasi dan hasil, run tanpa receiver sebagai blok lokal, run pada nullable dengan safe-call, serta perbandingan dengan with.
Apa Itu run #
Signature run:
// Extension pada T
inline fun <T, R> T.run(block: T.() -> R): R
// Tanpa receiver — blok eksekusi lokal
inline fun <R> run(block: () -> R): R- Receiver: objek dipanggil
run(tersedia sebagaithis). - Return: hasil block.
- Use case utama: eksekusi block pada receiver, ambil hasil.
Tabel Perbandingan run dengan Scope Lain #
| Aspek | run |
|---|---|
| Receiver | this (objek dipanggil run) |
| Return | lambda result |
| Idiomatic use | Eksekusi block pada receiver, ambil hasil |
| Bisa dipakai tanpa receiver | Ya — sebagai blok lokal |
Pola run di Kode Nyata #
Mari kita lihat empat pola run yang sering muncul.
// run_example.kt
// run: receiver `this`, mengembalikan lambda result.
// Cocok untuk eksekusi blok pada receiver dan mengembalikan hasil.
class StringBuilder2 {
val parts = mutableListOf<String>()
fun tambah(s: String) {
parts.add(s)
}
fun build(): String = parts.joinToString(", ")
}
fun main() {
// Pola 1: run pada instance untuk menggabungkan konfigurasi dan hasil.
val pesan = StringBuilder2().run {
tambah("Halo")
tambah("Budi")
tambah("2026")
build()
}
println("Hasil run: $pesan")
// Pola 2: run tanpa receiver — sebagai blok eksekusi lokal.
val hasilHitung = run {
val a = 10
val b = 20
val c = a + b
"Total a + b + c = ${a + b + c}"
}
println(hasilHitung)
// Pola 3: run pada nullable dengan safe-call.
val nama: String? = "Siti"
val panjang = nama?.run {
println("Memproses nama: $this")
length
}
println("Panjang: $panjang")
// Pola 4: run vs with — run sebagai extension, with sebagai function biasa.
val sb = StringBuilder()
val html = sb.run {
append("<html>")
append("<body>Halo</body>")
append("</html>")
toString()
}
println("HTML: $html")
}Output yang Dihasilkan:
Hasil run: Halo, Budi, 2026
Total a + b + c = 60
Memproses nama: Siti
Panjang: 4
HTML: <html><body>Halo</body></html>Mari kita telaah baris-baris kode di atas:
- Baris 13-19 (
val pesan = StringBuilder2().run { ... }): pola konfigurasi + hasil. InstanceStringBuilder2dibuat danrundipanggil. Di dalam block,thisadalah instance tersebut — kita memanggiltambah(...)tanpa prefix. Block ditutup denganbuild()yang mengembalikan string. Hasil string menjadi nilaipesan. - Baris 22-27 (
val hasilHitung = run { ... }): pola run tanpa receiver. Bentuk ini adalah blok eksekusi lokal — beberapa variabel lokal dihitung dan ditutup dengan ekspresi string. Manfaat: variabela,b,ctidak bocor ke scope luar. - Baris 30-34 (
val panjang = nama?.run { ... }): pola safe-call pada nullable.nama?.runhanya menjalankan block bilanamatidak null. Di dalam block,thisadalahStringnon-null — kita memanggillengthtanpa prefix. Bilanamanull, hasilnull. - Baris 37-43 (
val html = sb.run { append(...); ...; toString() }): pola extension + lambda result.sbadalahStringBuilder. Di dalam block,thisadalahsb— kita memanggilappendbeberapa kali lalutoString()untuk menghasilkan string final. Pola ini sering dipakai untuk build string/HTML.
run vs with #
run dan with mirip — keduanya memakai this dan mengembalikan lambda result. Perbedaan: run adalah extension function (dipanggil pada objek), sedangkan with adalah function biasa (menerima objek sebagai parameter pertama).
| Aspek | run | with |
|---|---|---|
| Bentuk | obj.run { ... } | with(obj) { ... } |
| Receiver | this | this |
| Return | lambda result | lambda result |
| Nullable safety | Bisa obj?.run { } | Tidak bisa langsung |
run Tanpa Receiver — Blok Lokal #
Salah satu penggunaan run yang kurang dikenal adalah sebagai blok eksekusi lokal tanpa receiver. Pola ini berguna untuk mengelompokkan beberapa perhitungan menjadi satu ekspresi tanpa membocorkan variabel lokal ke scope luar.
val hasil = run {
val a = bacaConfig()
val b = hitungBerdasarkan(a)
val c = validasi(b)
c.toString()
}
// a, b, c tidak tersedia di luar blockReferensi Lanjutan #
- Scope functions
— panduan resmi
rununtuk eksekusi block pada receiver - Higher-order functions and lambdas
— dasar lambda receiver pada
run
Penutup #
run adalah scope function fleksibel yang dapat dipakai sebagai extension (menggunakan this) atau blok lokal (tanpa receiver). Dengan run, kita dapat mengelompokkan konfigurasi dan hasil dalam satu ekspresi, mengelola nullable dengan safe-call, dan membatasi scope variabel lokal. Selanjutnya, kita akan mempelajari with — function non-extension yang dipakai khusus untuk mengelompokkan panggilan pada objek yang sama.