Lewati ke konten

Match di Rust

match membandingkan sebuah nilai dengan daftar pola (pattern) dan menjalankan kode untuk pola yang cocok. Kalau kamu pernah memakai switch, anggap saja match sebagai versi switch yang jauh lebih kuat. Kalau belum pernah, tidak masalah, karena match tetap salah satu hal paling berguna untuk dipelajari sejak awal.

fn main() {
let day = 3;
match day {
1 => println!("Senin"),
2 => println!("Selasa"),
3 => println!("Rabu"),
4 => println!("Kamis"),
5 => println!("Jumat"),
_ => println!("Akhir pekan"),
}
}

Output:

Rabu
▶ Coba sendiri

_ adalah pola penampung (catch-all): ia cocok dengan apa saja yang tidak tercantum di atasnya. match mewajibkan setiap kemungkinan nilai ditangani, jadi _ biasanya ada untuk menangani “semua sisanya”.

Kamu bisa mengelompokkan beberapa nilai dalam satu cabang (arm) memakai |:

fn main() {
let day = 6;
match day {
1 | 2 | 3 | 4 | 5 => println!("Hari kerja"),
6 | 7 => println!("Akhir pekan"),
_ => println!("Bukan hari yang valid"),
}
}
▶ Coba sendiri

Untuk angka, kamu bisa mencocokkan satu rentang (range) sekaligus dengan ..=:

fn main() {
let score = 85;
match score {
90..=100 => println!("A"),
75..=89 => println!("B"),
60..=74 => println!("C"),
_ => println!("F"),
}
}
▶ Coba sendiri

Sama seperti if, match bisa menghasilkan nilai:

fn main() {
let day = 6;
let kind = match day {
1 | 2 | 3 | 4 | 5 => "hari kerja",
6 | 7 => "akhir pekan",
_ => "tidak dikenal",
};
println!("{kind}");
}
▶ Coba sendiri

match bukan hanya untuk angka. Ia juga bisa dipakai pada string slice (&str) dan karakter, dan rentang karakter seperti 'a'..='z' bekerja persis seperti rentang angka:

fn main() {
let command = "stop";
match command {
"start" => println!("Memulai..."),
"stop" | "quit" => println!("Berhenti."),
_ => println!("Perintah tidak dikenal: {command}"),
}
let letter = 'k';
let kind = match letter {
'a' | 'e' | 'i' | 'o' | 'u' => "huruf vokal",
'a'..='z' => "huruf konsonan",
'0'..='9' => "angka",
_ => "hal lain",
};
println!("'{letter}' adalah {kind}");
let name = String::from("Ferris");
match name.as_str() {
"Ferris" => println!("Hai, kepiting!"),
_ => println!("Hai, {name}!"),
}
}

Output:

Berhenti.
'k' adalah huruf konsonan
Hai, kepiting!
▶ Coba sendiri

Ada dua hal yang perlu diperhatikan di sini:

  • Urutan itu penting. 'a' juga termasuk dalam 'a'..='z', tapi cabang huruf vokal ada lebih dulu, jadi huruf vokal tidak pernah sampai ke cabang konsonan. Rust selalu memilih cabang pertama yang cocok.
  • String butuh .as_str(). Teks yang ditulis di dalam tanda kutip, seperti "Ferris", adalah &str. Kalau kamu langsung mencocokkan sebuah String dengan pola seperti itu, Rust berhenti dengan pesan error[E0308]: mismatched types ... expected String, found &str (tipenya tidak cocok: yang diharapkan String, yang ditemukan &str). Memanggil .as_str() memberimu tampilan &str dari String tersebut, sehingga bisa dibandingkan dengan pola-polanya. (Lihat halaman String untuk perbedaan keduanya.)

Pencocokan membedakan huruf besar dan kecil: "Stop" tidak akan cocok dengan "stop". Kalau teksnya berasal dari pengguna, trik yang umum dipakai adalah mencocokkan input.to_lowercase().as_str().

Keduanya bisa dipakai untuk pengecekan benar/salah yang sederhana, tapi match mulai unggul begitu kemungkinannya lebih dari dua atau tiga. Kodenya lebih enak dibaca daripada rantai else if yang panjang, dan compiler mengecek bahwa semua kemungkinan sudah kamu tangani. Untuk satu kondisi ya/tidak, if/else tetap alat yang tepat.

Simpan nomor bulan month (2). Pakai match sebagai ekspresi untuk menghitung jumlah harinya (abaikan tahun kabisat), lalu tampilkan Bulan 2 punya 28 hari. Petunjuk: bulan 1, 3, 5, 7, 8, 10, dan 12 punya 31 hari; kelompokkan semuanya dalam satu cabang dengan |.

Lihat solusi
fn main() {
let month = 2;
let days = match month {
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
4 | 6 | 9 | 11 => 30,
2 => 28,
_ => 0, // bukan bulan yang valid
};
println!("Bulan {month} punya {days} hari");
}

Output:

Bulan 2 punya 28 hari
▶ Coba sendiri

Server web menjawab dengan sebuah angka. Ubah sebuah code menjadi arti singkatnya: 200 adalah "OK", 404 adalah "Not Found", kode 400–499 lainnya adalah "Error klien", 500–599 adalah "Error server", dan selain itu "Tidak dikenal". Coba dengan 503. Petunjuk: taruh cabang 404 yang persis itu di atas rentang 400..=499, kalau tidak, cabang itu tidak akan pernah tercapai.

Lihat solusi
fn main() {
let code = 503;
let meaning = match code {
200 => "OK",
404 => "Not Found", // harus ada sebelum rentang 400..=499
400..=499 => "Error klien",
500..=599 => "Error server",
_ => "Tidak dikenal",
};
println!("{code}: {meaning}");
}

Output:

503: Error server
▶ Coba sendiri

"OK" dan "Not Found" sengaja tidak diterjemahkan, karena itulah nama resmi status HTTP tersebut.

  • match membandingkan sebuah nilai dengan pola-pola dan menjalankan cabang yang cocok.
  • Setiap kemungkinan nilai harus ditangani. Pakai _ sebagai penampung.
  • Gabungkan beberapa nilai dengan |, atau cocokkan sebuah rentang dengan ..=.
  • Kamu juga bisa mencocokkan teks &str dan nilai char; pakai .as_str() untuk mencocokkan sebuah String.
  • Seperti if, match bisa dipakai sebagai ekspresi untuk menghasilkan nilai.

Kuis singkat

1. Apa fungsi pola _ di dalam ekspresi match?

2. Apa yang terjadi kalau sebuah ekspresi match tidak menangani semua kemungkinan nilai dan tidak punya cabang _?

3. Bagaimana cara mencocokkan beberapa nilai dalam satu cabang, misalnya 1, 2, atau 3?

Skor: 0 / 3