Topik ini membahas cara mengarahkan jalannya program Rust: percabangan dengan if yang sekaligus berfungsi sebagai ekspresi, perulangan dengan loop, while, dan for, serta pemakaian rentang pada perulangan for. Setelah membacanya, pembaca dapat memilih bentuk alur kontrol yang paling aman untuk setiap kebutuhan dan memahami syarat tipe yang menyertainya.
Percabangan dengan if#
Percabangan memilih blok kode yang dijalankan berdasarkan sebuah kondisi. Kata kunci if diikuti kondisi tanpa tanda kurung, lalu blok kodenya dibatasi kurung kurawal, dan titik koma tidak ditulis setelah kurung kurawal penutup.
fn main() {
let angka = 7;
if angka % 2 == 0 {
println!("{angka} adalah bilangan genap");
} else {
println!("{angka} adalah bilangan ganjil");
}
}7 adalah bilangan ganjilKondisi wajib bertipe bool karena Rust tidak menganggap bilangan maupun nilai lain sebagai benar atau salah secara implisit. Tanda kurung di sekitar kondisi tidak diperlukan, dan pemakaiannya justru memicu peringatan unnecessary parentheses dari compiler. Blok else dijalankan ketika kondisi salah. Rantai banyak kondisi disusun dengan else if, dan pemeriksaannya berhenti pada kondisi pertama yang terpenuhi.
fn main() {
let nilai = 78;
if nilai >= 90 {
println!("predikat A");
} else if nilai >= 80 {
println!("predikat B");
} else if nilai >= 70 {
println!("predikat C");
} else {
println!("predikat D");
}
}predikat CNilai 78 gagal pada dua kondisi pertama dan berhenti di kondisi ketiga, sehingga hanya satu blok yang dijalankan. Setiap cabang else if hanya diperiksa apabila semua kondisi sebelumnya bernilai salah, sehingga urutan penulisan menentukan hasil. Ketika rantai kondisi memeriksa satu nilai terhadap banyak pola, pencocokan dengan match yang dibahas pada modul struct dan enum menjadi alternatif yang lebih ringkas.
if sebagai ekspresi#
Blok if di Rust adalah ekspresi, sehingga hasilnya dapat langsung diikat ke sebuah variabel. Syaratnya satu, yaitu kedua cabang harus menghasilkan tipe yang sama.
fn main() {
let kondisi = true;
let angka = if kondisi { 10 } else { 20 };
println!("nilai angka: {angka}");
}nilai angka: 10Pola ini menggantikan kebiasaan dari bahasa lain yang mendeklarasikan variabel kosong terlebih dahulu, lalu mengisinya di setiap cabang. Nilai if ditentukan oleh ekspresi terakhir tiap blok tanpa titik koma, sama seperti nilai blok pada umumnya. Ketika salah satu cabang bernilai 10 dan cabang lainnya bernilai teks, compiler menolak kedua tipe yang berbeda tersebut.
Cabang else wajib ada ketika nilai if dipakai. Tanpa else, nilai keseluruhan ekspresi pada saat kondisi salah adalah tipe unit (), sehingga penulisan let angka = if kondisi { 10 }; ditolak compiler dengan error E0317. Ketika if hanya menjalankan blok dan hasilnya tidak diambil sebagai nilai, cabang else boleh ditiadakan.
Perulangan dengan loop#
Kata kunci loop menjalankan blok kode tanpa henti sampai bertemu perintah break. Perintah break juga dapat membawa nilai yang menjadi hasil seluruh ekspresi loop.
fn main() {
let mut hitung = 0;
let hasil = loop {
hitung += 1;
if hitung == 10 {
break hitung * 2;
}
};
println!("hasil loop: {hasil}");
}hasil loop: 20Perulangan berhenti ketika hitung mencapai 10, dan nilai break berupa 20 menjadi nilai variabel hasil. Bentuk ini berguna untuk perulangan pencarian yang mengembalikan sesuatu begitu ditemukan. Ketika perulangan bersarang, label seperti 'luar: dapat dipasang pada loop terluar supaya break 'luar menghentikan seluruh perulangan sekaligus, bukan hanya perulangan terdalam tempat perintah ditulis.
Kata kunci continue melompati sisa blok dan langsung memulai putaran berikutnya. Perintah ini berlaku pada semua bentuk perulangan. Tanpa break, loop berjalan tanpa akhir, sehingga pola yang mengulang sampai sebuah operasi berhasil merupakan kandidat alami untuk loop.
Perulangan dengan while#
Perulangan while memeriksa kondisi sebelum setiap putaran dan berhenti ketika kondisi menjadi salah. Bentuk ini cocok ketika jumlah putaran tidak diketahui di depan, misalnya memproses antrean yang isinya berkurang. Kondisi diperiksa juga sebelum putaran pertama, sehingga blok perulangan tidak dijalankan sama sekali ketika kondisi sudah bernilai salah sejak awal.
fn main() {
let mut sisa = 3;
while sisa > 0 {
println!("sisa antrean: {sisa}");
sisa -= 1;
}
println!("antrean selesai");
}sisa antrean: 3
sisa antrean: 2
sisa antrean: 1
antrean selesaiKondisi sisa > 0 bernilai benar pada tiga putaran pertama, lalu salah setelah sisa mencapai nol, dan eksekusi lanjut ke baris setelah kurung kurawal penutup. Perintah break dan continue juga berlaku pada while dengan perilaku yang sama seperti pada loop. Perhatikan bahwa pengubahan nilai sisa di dalam blok merupakan bagian penting dari perulangan yang benar, sebab tanpa perubahan tersebut kondisi tidak pernah menjadi salah dan perulangan tidak berhenti. Alur pengambilan keputusan berulang ini tampak pada diagram berikut.
Perulangan dengan for dan rentang#
Perulangan for menjalankan blok kode untuk setiap nilai yang dihasilkan sebuah iterator, yakni sumber nilai yang mengeluarkan isinya satu per satu. Bentuk ini menjadi pilihan utama di Rust karena aman dari kesalahan indeks. Sumber nilai yang paling lazim adalah rentang (range).
fn main() {
for angka in 1..4 {
println!("angka: {angka}");
}
for detik in (1..=3).rev() {
println!("hitung mundur: {detik}");
}
let nilai = [80, 90, 100];
for n in nilai {
println!("nilai: {n}");
}
}angka: 1
angka: 2
angka: 3
hitung mundur: 3
hitung mundur: 2
hitung mundur: 1
nilai: 80
nilai: 90
nilai: 100Rentang 1..4 menghasilkan nilai 1, 2, dan 3 tanpa angka 4, sedangkan 1..=3 memuat angka 3 di ujungnya. Metode .rev() membalik urutan sehingga cocok untuk hitung mundur. Array juga dapat diiterasi langsung elemen demi elemen tanpa indeks, dan tiap elemen tersedia sebagai variabel n di dalam blok. Ketika jumlah putaran sudah diketahui atau sumber nilainya berupa koleksi, bentuk for umumnya menjadi pilihan yang tepat, dan panduan singkatnya tersedia pada tabel berikut.
| Bentuk | Kapan dipakai |
|---|---|
loop | perulangan tanpa batas sampai break, termasuk pencarian yang mengembalikan nilai |
while | jumlah putaran tidak diketahui dan bergantung pada kondisi yang berubah |
for | mengiterasi rentang, array, atau koleksi dengan jumlah elemen yang jelas |
Bentuk for juga bekerja sama dengan iterator yang dibahas pada modul iterator dan closure. Rentang dan array pada contoh di atas hanyalah dua contoh sumber nilai untuk for, karena banyak jenis koleksi lain dapat diiterasi dengan cara yang sama. Pola yang diperkenalkan pada topik ini tetap dipakai pada kode tingkat lanjut.
Kesalahan umum#
Memakai bilangan sebagai kondisi. Kebiasaan dari bahasa yang menganggap bilangan nol sebagai salah langsung ditolak compiler, seperti contoh berikut.
printf 'fn main() {\n let angka = 3;\n if angka {\n println!("tiga");\n }\n}\n' > salah.rs
rustc --edition=2021 salah.rs 2>&1 | sed -n '1,7p'error[E0308]: mismatched types
--> salah.rs:3:8
|
3 | if angka {
| ^^^^^ expected `bool`, found integer
error: aborting due to 1 previous errorPerbaikannya adalah menuliskan perbandingan yang jelas, misalnya if angka != 0 ketika maksudnya memeriksa bilangan tidak nol. Error yang sama muncul pada kondisi while karena kedua konstruksi menuntut tipe bool.
Mencampur tipe cabang pada if sebagai ekspresi. Penulisan if kondisi { 10 } else { "sepuluh" } gagal dikompilasi karena satu cabang bernilai bilangan dan cabang lainnya bernilai teks, dan error yang muncul adalah E0308 seperti pada kasus tipe yang tidak cocok lainnya. Ubah salah satu cabang atau konversikan nilainya sehingga keduanya bertipe sama. Pemakaian seperti ini biasanya menandakan kedua cabang sebenarnya menghasilkan hal yang berbeda sehingga lebih tepat dipecah menjadi percabangan biasa.
Ringkasan#
- Kondisi
ifdanwhilewajib bertipebooltanpa konversi implisit dari bilangan maupun nilai lain. ifadalah ekspresi yang hasilnya dapat diikat ke variabel asalkan semua cabang bertipe sama.loopberjalan tanpa henti sampaibreak, danbreakdapat membawa nilai hasil ekspresiloop.whilememeriksa kondisi sebelum setiap putaran, sedangkan label mengaturbreakpada perulangan bersarang.formengiterasi rentanga..b,a..=b, maupun koleksi langsung, dan menjadi bentuk perulangan paling aman.
Referensi#
- Control Flow — The Rust Book
—
if,loop,while,for, dan interaksibreakdengan nilai kembalian. - if/else — Rust by Example
— Contoh percabangan termasuk
ifsebagai ekspresi. - for dan range — Rust by Example — Variasi iterasi rentang beserta metode pendukungnya.