Lewati ke konten

If Let / While Let di Rust

Kamu sudah memakai match untuk menangani Option dan Result. Tapi sering kali, kamu sebenarnya hanya peduli pada satu pola dan ingin mengabaikan sisanya. Menulis match lengkap dengan cabang _ => {} hanya untuk tidak melakukan apa-apa memang bisa jalan, tapi terlalu bertele-tele untuk situasi seperti itu. if let adalah jalan pintasnya.

fn main() {
let age: Option<i32> = Some(30);
match age {
Some(value) => println!("Umurnya {value}"),
_ => {}, // kita sebenarnya tidak peduli dengan kasus ini
}
}

_ => {} itu tidak melakukan apa-apa selain memenuhi aturan match bahwa “semua kemungkinan harus ditangani”. Kalau kamu hanya ingin bertindak saat nilainya Some, kodenya terlalu panjang untuk ide sesederhana itu.

fn main() {
let age: Option<i32> = Some(30);
if let Some(value) = age {
println!("Umurnya {value}");
}
}

Output:

Umurnya 30
▶ Coba sendiri

Bacanya begini: “kalau age cocok dengan pola Some(value), jalankan blok ini, dengan value berisi nilai yang ada di dalamnya.” Kalau age bernilai None, bloknya dilewati begitu saja: tidak ada error, tidak ada yang ditampilkan.

if let bisa punya else, sama seperti if biasa:

fn main() {
let age: Option<i32> = None;
if let Some(value) = age {
println!("Umurnya {value}");
} else {
println!("Umur tidak diisi");
}
}
▶ Coba sendiri

Cara kerjanya sama dengan Result, yang sudah kamu kenal di halaman Result:

fn main() {
let input = "42";
if let Ok(number) = input.parse::<i32>() {
println!("Hasil parse: {number}");
} else {
println!("Tidak bisa di-parse");
}
}
▶ Coba sendiri

Sama seperti if punya else if, if let bisa diikuti else if let. Rust mencoba setiap pola secara bergantian dan menjalankan blok pertama yang cocok. Ini berguna kalau ada beberapa tempat untuk mencari sebuah nilai, diurutkan dari yang paling diutamakan:

fn main() {
let nickname: Option<&str> = None;
let full_name: Option<&str> = Some("Ferris Crab");
if let Some(nick) = nickname {
println!("Hai, {nick}!");
} else if let Some(name) = full_name {
println!("Halo, {name}.");
} else {
println!("Halo, orang asing.");
}
}

Output:

Halo, Ferris Crab.
▶ Coba sendiri

nickname bernilai None, jadi blok pertama dilewati. full_name cocok dengan Some(name), jadi blok itu yang dijalankan, dan else terakhir tidak pernah tercapai. Kamu juga bisa menyisipkan kondisi biasa, seperti else if is_admin { ... }, di mana saja dalam rangkaian itu.

Setiap variabel hanya ada di dalam bloknya sendiri: nick tidak bisa dipakai di blok kedua, dan name tidak bisa dipakai setelah rangkaiannya selesai. Kalau kamu butuh nilai yang sudah dibongkar untuk sisa kode kamu, lihat let-else di halaman Pattern Matching.

while let menerapkan ide yang sama pada perulangan (loop): terus mengulang selama sebuah nilai cocok dengan pola. Ini sangat berguna untuk mengosongkan sebuah koleksi:

fn main() {
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("{top}");
}
}

Output:

3
2
1
▶ Coba sendiri

.pop() mengembalikan Some(value) selama masih ada isinya, dan None begitu vektornya kosong. Saat itulah while let otomatis menghentikan perulangannya. Tidak perlu mengecek panjangnya secara manual.

Pakai match kalau kamu memang perlu menangani beberapa kasus dengan cara yang berbeda-beda. Pakai if let kalau hanya ada satu pola yang kamu pedulikan dan sisanya cukup diabaikan. if let bukan pengganti match, hanya cara yang lebih singkat untuk menulis kasus umum “aku cuma peduli satu cabang”.

Mulai dengan let mut numbers = vec![4, 8, 15]; dan total bernilai 0. Pakai while let dengan .pop() untuk mengambil angka dari ujung satu per satu, tambahkan masing-masing ke total, lalu tampilkan angkanya dan total yang baru. Petunjuk: total butuh mut, dan total += n menambahkan nilai ke dalamnya.

Lihat solusi
fn main() {
let mut numbers = vec![4, 8, 15];
let mut total = 0;
while let Some(n) = numbers.pop() {
total += n;
println!("ambil {n}, total sekarang {total}");
}
}

Output:

ambil 15, total sekarang 15
ambil 8, total sekarang 23
ambil 4, total sekarang 27
▶ Coba sendiri

.pop() mengambil dari ujung, makanya 15 keluar lebih dulu.

Simpan let input = "17";. Kalau teks itu bisa di-parse sebagai u32, tampilkan apakah umur itu termasuk dewasa (18 ke atas) atau di bawah umur. Kalau tidak bisa di-parse, tampilkan bahwa itu bukan angka. Coba juga ubah input menjadi "abc". Petunjuk: taruh if / else biasa di dalam blok if let.

Lihat solusi
fn main() {
let input = "17";
if let Ok(age) = input.parse::<u32>() {
if age >= 18 {
println!("{age} sudah dewasa");
} else {
println!("{age} masih di bawah umur");
}
} else {
println!("'{input}' bukan angka");
}
}

Output:

17 masih di bawah umur
▶ Coba sendiri

Dengan input = "abc", parse-nya gagal, else di luar dijalankan, dan program menampilkan 'abc' bukan angka.

  • if let Pola = nilai { ... } menjalankan blok hanya kalau nilai cocok dengan Pola. Sisanya dilewati diam-diam.
  • Tambahkan else untuk menangani kasus yang tidak cocok, sama seperti if biasa, dan rangkai beberapa pola dengan else if let.
  • while let Pola = nilai { ... } terus mengulang selama nilainya masih cocok, berguna untuk mengosongkan koleksi dengan .pop().
  • Pakai if let/while let kalau kamu hanya peduli satu pola; pakai match kalau kamu perlu menangani beberapa kasus secara berbeda.

Kuis singkat

1. Apa yang terjadi saat if let Some(value) = age dijalankan dan age bernilai None?

2. Kapan sebaiknya kamu memakai match, bukan if let?

3. Pada while let Some(top) = stack.pop() { ... }, kapan perulangannya berhenti?

Skor: 0 / 3