Sejauh ini seluruh program yang kita tulis berjalan lurus dari baris pertama hingga baris terakhir tanpa jalan memutar. Program dunia nyata hampir selalu mengambil keputusan: aplikasi kasir menolak pesanan saat stok habis, aplikasi cuaca menampilkan peringatan ketika suhu melebihi ambang batas, dan sistem akademik menentukan predikat kelulusan dari nilai mahasiswa. Kebutuhan semacam ini diselesaikan dengan percabangan (branch) — struktur yang memilih blok kode mana yang boleh dieksekusi berdasarkan sebuah kondisi. Pada Chapter ini kita akan mempelajari bentuk percabangan if, else if, dan else di Rust, termasuk aturan tipenya yang lebih ketat dibandingkan bahasa pemrograman lain.

Sintaks Dasar if #

Sebuah percabangan dimulai dengan kata kunci if yang diikuti kondisi tanpa tanda kurung, lalu blok kode di dalam kurung kurawal. Rust mengevaluasi kondisi tersebut menjadi nilai bool; apabila hasilnya true, blok kode di dalam kurung kurawal dieksekusi, dan apabila hasilnya false, blok kode tersebut dilewati sepenuhnya. Mari kita lihat wujudnya dalam program sederhana pemeriksa suhu:

rust
fn main() {
    let temperature = 31;

    if temperature > 30 {
        println!("Cuaca hari ini sangat panas.");
    }
}

Output yang Dihasilkan:

text
Cuaca hari ini sangat panas.

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 2 (let temperature = 31;): program menyimpan nilai integer 31 ke dalam variabel temperature yang bertipe i32 (hasil inferensi tipe dari literal integer).
  2. Baris 4 (if temperature > 30 {): Rust membaca nilai temperature lalu membandingkannya dengan 30 menggunakan operator lebih besar dari (>). Hasil perbandingan bernilai true, sehingga eksekusi berlanjut ke dalam blok kurung kurawal.
  3. Baris 5 (println!("Cuaca hari ini sangat panas.");): macro println! mencetak pesan ke terminal karena kondisi pada baris sebelumnya bernilai true.

Apabila kita mengubah nilai temperature menjadi 25, ekspresi temperature > 30 bernilai false, blok kurung kurawal dilewati, dan program berakhir tanpa mencetak apa pun. Perhatikan pula bahwa tanda kurung di sekeliling kondisi tidak perlu dituliskan — penulisan if (temperature > 30) tetap sah secara sintaks di Rust, tetapi compiler memberikan peringatan unnecessary parentheses karena idiom Rust tidak memakai tanda kurung pada kondisi.

Tabel berikut merangkum perbedaan penulisan if di Rust dibandingkan bahasa yang mungkin sudah kita kenal:

AspekC / PHP / JavaScriptRust
Tanda kurung di sekitar kondisiWajibTidak digunakan (tidak idiomatik)
Kurung kurawal untuk satu statementOpsionalWajib selalu ditulis
Tipe hasil kondisiFleksibel (truthy/falsy)Harus tepat bool

Kurung kurawal yang wajib ditulis membuat batas awal dan akhir blok percabangan selalu terlihat jelas. Ketika kita menambahkan statement kedua di dalam blok, kita tidak akan pernah mengalami galat klasik “statement kedua selalu dieksekusi” yang kerap muncul pada bahasa yang mengizinkan blok tanpa kurung kurawal.

else dan else if #

Satu kondisi jarang cukup untuk keputusan yang berjenjang. Kata kunci else if menghubungkan serangkaian kondisi yang diperiksa berurutan dari atas ke bawah, dan kata kunci else menjadi penampung untuk semua keadaan yang tidak terpenuhi. Rust mengevaluasi setiap kondisi satu per satu; cabang pertama yang bernilai true dieksekusi, lalu seluruh cabang lainnya dilewati tanpa diperiksa lagi. Mari kita terapkan pada penentuan predikat nilai mahasiswa:

rust
fn main() {
    let score = 78;

    if score >= 90 {
        println!("Predikat: A");
    } else if score >= 80 {
        println!("Predikat: B");
    } else if score >= 70 {
        println!("Predikat: C");
    } else {
        println!("Predikat: D");
    }
}

Output yang Dihasilkan:

text
Predikat: C

Mari kita uraikan alur eksekusi pada program di atas:

  1. Baris 2 (let score = 78;): variabel score dibuat dengan nilai integer 78.
  2. Baris 4 (if score >= 90 {): Rust membandingkan 78 >= 90 dan memperoleh false, sehingga blok predikat A dilewati dan pemeriksaan berlanjut ke cabang berikutnya.
  3. Baris 6 (} else if score >= 80 {): perbandingan 78 >= 80 juga menghasilkan false, sehingga blok predikat B dilewati.
  4. Baris 8 (} else if score >= 70 {): perbandingan 78 >= 70 menghasilkan true, sehingga blok predikat C dieksekusi.
  5. Baris 9 (println!("Predikat: C");): macro println! mencetak Predikat: C, kemudian eksekusi melompat ke akhir rantai percabangan.
  6. Baris 10 (} else {): blok else tidak pernah diperiksa karena sudah ada cabang sebelumnya yang terpenuhi.

Urutan cabang menentukan hasil akhirnya. Apabila kita memindahkan cabang score >= 70 ke urutan paling awal, nilai 78 akan berhenti di cabang tersebut dan mendapat predikat C meskipun nilai tersebut juga memenuhi syarat cabang yang lebih tinggi — contoh sederhana bahwa kondisi paling ketat sebaiknya ditempatkan di urutan paling awal. Blok else bersifat opsional, tetapi kehadiran blok else menjamin tepat satu cabang dieksekusi ketika semua kondisi sebelumnya bernilai false.

Kondisi if Harus Bertipe bool #

Pemrogram PHP atau JavaScript terbiasa menuliskan kondisi berupa angka karena kedua bahasa mengkonversi nilai secara implisit: angka 0 dianggap false dan nilai lain dianggap true. Rust tidak melakukan konversi tersebut sama sekali. Kondisi pada if wajib menghasilkan tipe bool secara eksplisit. Mari kita buktikan dengan sengaja menuliskan kondisi bertipe integer:

rust
fn main() {
    let stock = 0;

    if stock {
        println!("Stok tersedia.");
    }
}

Output yang Dihasilkan (galat kompilasi):

text
error[E0308]: mismatched types
 --> main.rs:4:8
  |
4 |     if stock {
  |        ^^^^^ expected `bool`, found integer

error: aborting due to 1 previous error

Compiler menolak kode di atas pada saat kompilasi dengan galat mismatched types karena stock bertipe integer, sedangkan if mengharapkan tipe bool. Penolakan dini semacam ini bukan hambatan, melainkan perlindungan: maksud “angka nol berarti stok kosong” tertangkap sebagai kode ambigu sebelum program sempat berjalan. Kita harus menuliskan perbandingan secara eksplisit sehingga maksud kode terbaca jelas:

rust
fn main() {
    let stock = 0;

    if stock == 0 {
        println!("Stok habis, pesanan ditolak.");
    } else {
        println!("Stok tersedia sebanyak {} item.", stock);
    }
}

Output yang Dihasilkan:

text
Stok habis, pesanan ditolak.

Pada versi yang telah diperbaiki, ekspresi stock == 0 menghasilkan tipe bool sehingga proses kompilasi berhasil. Kondisi stock == 0 bernilai true, blok if dieksekusi, dan blok else yang mencetak jumlah stok dilewati. Operator pembanding seperti ==, !=, >, dan <= selalu menghasilkan bool, sehingga kebiasaan menuliskan perbandingan eksplisit menjadikan setiap kondisi self-documenting.

Ringkasan #

Percabangan di Rust ditulis dengan if, else if, dan else tanpa tanda kurung di sekitar kondisi, dengan kurung kurawal yang wajib ditulis, dan dengan kondisi yang harus bertipe bool secara eksplisit. Cabang-cabang diperiksa berurutan dari atas ke bawah, dan hanya cabang pertama yang terpenuhi yang dieksekusi. Kebiasaan menulis perbandingan eksplisit seperti stock == 0 menjadikan maksud setiap kondisi terbaca jelas sekaligus aman dari konversi implisit. Pada Chapter selanjutnya kita akan mempelajari loop, struktur yang mengulang eksekusi blok kode tanpa henti sampai kita memutuskan untuk berhenti.