let adalah scope function paling sering dipakai untuk null-safety dan transformasi nilai. Function ini memberi akses ke objek via parameter implisit it dan mengembalikan hasil block sebagai nilai kembalian. Pada chapter ini kita akan membedah empat pola penggunaan let yang umum di kode Kotlin modern — null-safety via safe-call, transformasi nilai, scope variabel lokal, dan rename it. Kita juga akan melihat kapan let tidak diperlukan agar tidak dipakai berlebihan.

Apa Itu let #

let adalah extension function dengan signature:

kotlin Signature let
inline fun <T, R> T.let(block: (T) -> R): R
  • Receiver: objek yang dipanggil let (tersedia di block sebagai it).
  • Return: hasil block block(it), bertipe R.
  • Use case utama: null-safety, transformasi nilai.

Tabel Perbandingan let dengan Scope Lain #

Aspeklet
Receiverit (parameter implisit)
Returnlambda result
Idiomatic useNull-safety, transformasi
Bisa safe-callYa — obj?.let { ... }

Pola let di Kode Nyata #

Mari kita lihat empat pola let yang sering muncul.

kotlin
// let_example.kt
// let: receiver `it`, mengembalikan lambda result.
// Cocok untuk null-safety dan transformasi.

data class Pengguna(val nama: String, val umur: Int)

fun temukanPengguna(id: Int): Pengguna? {
    return if (id == 1) Pengguna("Budi", 25) else null
}

fun main() {
    // Pola 1: null-safety dengan safe-call + let.
    val hasil = temukanPengguna(1)
    hasil?.let { pengguna ->
        println("Ditemukan: ${pengguna.nama}, ${pengguna.umur} tahun")
    }

    val hasilKosong = temukanPengguna(99)
    hasilKosong?.let {
        println("Tidak akan tercetak")
    } ?: println("Pengguna tidak ditemukan")

    // Pola 2: transformasi nilai.
    val pesan = "Halo"
    val panjang = pesan.let { it.length }
    println("Panjang \"$pesan\": $panjang")

    // Pola 3: scope variabel lokal untuk menghindari pengulangan.
    val pengguna = Pengguna("Siti", 30)
    val info = pengguna.let {
        val status = if (it.umur >= 17) "dewasa" else "anak"
        "${it.nama} ($status)"
    }
    println("Info: $info")

    // Pola 4: rename `it` untuk kejelasan.
    val nomor = 42
    val deskripsi = nomor.let { n -> "angka favorit: $n" }
    println(deskripsi)

    // Perbandingan: tanpa let.
    val nama = "Andi"
    val sapa = "Halo, $nama!"  // tidak ada manfaat let di sini
    println(sapa)
}

Output yang Dihasilkan:

text
Ditemukan: Budi, 25 tahun
Pengguna tidak ditemukan
Panjang "Halo": 4
Info: Siti (dewasa)
angka favorit: 42
Halo, Andi!

Mari kita telaah baris-baris kode di atas:

  1. Baris 8-10 (fun temukanPengguna(id: Int): Pengguna?): function mengembalikan Pengguna? — bisa null. Pola let dipakai untuk menangani hasil dengan aman.
  2. Baris 14-17 (hasil?.let { pengguna -> println(...) }): pola null-safety. Safe-call ?. memastikan let hanya dipanggil bila hasil tidak null. Di dalam block, pengguna adalah instance non-null. Bila null, block tidak dijalankan.
  3. Baris 19-22 (hasilKosong?.let { ... } ?: println(...)): gabungan let dengan elvis operator ?:. Bila hasilKosong null, block let di-skip dan blok ?: dijalankan. Pola umum untuk “jika null, lakukan fallback”.
  4. Baris 25 (val panjang = pesan.let { it.length }): pola transformasi. let mengubah String menjadi Int (panjang). Block mengembalikan it.length yang menjadi nilai panjang.
  5. Baris 29-33 (val info = pengguna.let { ... }): pola scope variabel lokal. Di dalam block, kita buat val status lokal yang hanya bisa diakses di dalam block. Hasil block adalah string ringkasan. Manfaat: status tidak bocor ke scope luar.
  6. Baris 37 (val deskripsi = nomor.let { n -> "angka favorit: $n" }): pola rename it. Bila it kurang jelas, kita beri nama n eksplisit. Berguna saat body panjang atau konteks memerlukan nama deskriptif.
  7. Baris 41-43 (val sapa = "Halo, $nama!"): contoh di mana let tidak diperlukan. String template sudah cukup ringkas. Menambah let di sini hanya menambah noise tanpa manfaat.

Kapan Tidak Memakai let #

let sering disalahgunakan untuk “menjelaskan” kode yang sebetulnya sudah jelas. Beberapa tanda let berlebihan:

  • Block hanya berisi satu pemanggilan method — obj.let { it.foo() } lebih baik ditulis obj.foo().
  • Block hanya berisi string template — obj.let { "$it" } lebih baik ditulis "$obj".
  • Block tidak menggunakan nilai kembalian apa pun.

let untuk Reduksi Pengulangan #

Saat kita sering memanggil property atau method pada objek yang sama, let dapat mengurangi pengulangan dengan menyediakan nama singkat:

kotlin let untuk reduksi pengulangan
val pengguna = ambilPengguna()
val sapaan = pengguna.let { "${it.nama} - ${it.umur} - ${it.kota}" }

Tanpa let, kita menulis pengguna.nama, pengguna.umur, pengguna.kota — tiga kali prefix. let tidak wajib di sini, tetapi dapat membantu bila objek dari ekspresi panjang.

Referensi Lanjutan #

Penutup #

let adalah scope function paling sering dipakai untuk null-safety dan transformasi nilai. Dengan pola obj?.let { ... }, kita menjalankan block hanya bila objek non-null — menghindari null check eksplisit. let juga berguna untuk membentuk scope variabel lokal yang tidak bocor keluar. Selanjutnya, kita akan mempelajari run — scope function yang menggunakan this sebagai receiver dan cocok untuk eksekusi block pada objek dengan kembalian hasil.