Enum berbeda dari struct: satu enum dapat memuat beberapa varian dengan bentuk data yang berbeda-beda — ada varian tanpa data, varian dengan field bernama, dan varian dengan data posisi. Kekuatan match yang sesungguhnya baru terasa ketika pola tidak hanya memilih varian, tetapi juga menguraikan data di dalamnya pada arm yang sama. Chapter ini membahas penguraian ketiga bentuk varian tersebut, penggunaan pada Option, pola enum bersarang, cara mengabaikan sebagian isi varian, serta galat yang muncul ketika jumlah data pada pola tidak sesuai definisi varian.
Satu Arm untuk Setiap Bentuk Varian #
Setiap bentuk varian menuntut bentuk pola yang mengikutinya. Varian tanpa data cukup dituliskan path-nya saja, varian seperti struct memakai kurung kurawal berisi field, dan varian seperti tuple memakai kurung biasa berisi pola per posisi. Satu match dapat menampung ketiganya sekaligus, dan setiap data yang diuraikan langsung menjadi variabel lokal di dalam arm pemiliknya.
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
fn handle(message: Message) {
match message {
Message::Quit => println!("Sesi diakhiri."),
Message::Move { x, y } => println!("Pindah ke koordinat ({}, {}).", x, y),
Message::Write(text) => println!("Pesan terkirim: {}", text),
Message::ChangeColor(r, g, b) => println!("Warna diubah ke rgb({}, {}, {}).", r, g, b),
}
}
fn main() {
handle(Message::Quit);
handle(Message::Move { x: 10, y: -4 });
handle(Message::Write(String::from("Halo, Budi!")));
handle(Message::ChangeColor(10, 200, 60));
}Output yang Dihasilkan:
Sesi diakhiri.
Pindah ke koordinat (10, -4).
Pesan terkirim: Halo, Budi!
Warna diubah ke rgb(10, 200, 60).Mari kita bedah pola pada setiap arm:
- Baris 1–6 (
enum Message { ... }): enum mendemonstrasikan tiga bentuk varian —Quittanpa data,Movedengan field bernama,WritedanChangeColordengan data posisi. - Baris 9 (
match message {): parametermessagemenjadi nilai yang dicocokkan; kepemilikan nilainya berada di tangan fungsihandle. - Baris 11 (
Message::Quit => ...): varian tanpa data tidak butuh kurung — pathMessage::Quitsendiri adalah polanya. - Baris 12 (
Message::Move { x, y } => ...): varian bentuk struct diuraikan seperti pola struct; fieldxdanymenjadi variabel lokal di dalam arm ini. - Baris 13 (
Message::Write(text) => ...): varian tuple satu posisi diuraikan ke bindingtextbertipeString; karenaStringtidakCopy, isi teks berpindah darimessageketext. - Baris 14 (
Message::ChangeColor(r, g, b) => ...): tiga posisi data diikat menjadir,g, danb— urutan pola mengikuti urutan data pada varian. - Baris 18–21 (
handle(...)): empat pemanggilan menguji keempat arm; masing-masing menghasilkan satu baris keluaran sesuai varian yang dikirim.
Pengikatan data varian bersifat by value: pada arm Write, teks berpindah ke text dan message habis terpakai. Ketika data perlu dipakai ulang tanpa berpindah, pola dapat meminjamkannya lewat ref yang akan kita bahas pada chapter ref dan ref mut di Pola.
Menguraikan Option #
Option<T> adalah enum dua varian — Some(T) membawa satu data dan None tanpa data — sehingga seluruh teknik penguraian varian berlaku langsung. Posisi data di dalam Some dapat diisi pola apa pun, termasuk literal yang menguji isi tanpa mengikatnya:
fn main() {
let stock: Option<u32> = Some(12);
match stock {
Some(0) => println!("Stok kosong, segera isi ulang."),
Some(qty) => println!("Stok tersedia: {} unit.", qty),
None => println!("Produk tidak dilacak."),
}
}Output yang Dihasilkan:
Stok tersedia: 12 unit.Mari kita telaah pencocokannya:
- Baris 2 (
let stock: Option<u32> = Some(12);): variabelstockmemegang varianSomeberisi angka12; anotasi tipeu32menentukan tipe data di dalam varian. - Baris 5 (
Some(0) => ...): pola menguji varianSomesekaligus literal0di dalamnya — hanya cocok bila isinya tepat nol; nilai12gagal pada uji ini. - Baris 6 (
Some(qty) => ...): pola mengikat isiSomeke variabelqty; nilai12berpindah keqtysehingga arm ini terpilih. - Baris 7 (
None => ...): varian tanpa data menutup kemungkinan terakhir; ketiganya wajib ada agarmatchmemenuhi exhaustiveness.
Pola Enum Bersarang #
Data di dalam varian dapat berupa enum lain. Pola bersarang menggali lapisan demi lapisan dalam satu penulisan: Some(Some(value)) menguji varian Some pada lapisan luar sekaligus varian Some pada lapisan dalam, baru mengikat value pada intinya.
fn main() {
let backup: Option<Option<u32>> = Some(None);
match backup {
Some(Some(value)) => println!("Cadangan berisi {}.", value),
Some(None) => println!("Slot cadangan ada, tetapi kosong."),
None => println!("Tidak ada slot cadangan."),
}
}Output yang Dihasilkan:
Slot cadangan ada, tetapi kosong.Mari kita bedah ketiga armnya:
- Baris 2 (
let backup: Option<Option<u32>> = Some(None);): lapisan luarSomemembungkusNone— slot cadangan tersedia tetapi kosong. - Baris 5 (
Some(Some(value)) => ...): pola paling dalam mengujiSomedua kali; arm ini tercapai bila cadangan benar-benar berisi angka, laluvaluemengikat angka tersebut. - Baris 6 (
Some(None) => ...): lapisan luarSome, lapisan dalamNone— persis kondisi data kita, sehingga baris inilah yang tercetak. - Baris 7 (
None => ...): pola untuk slot yang sama sekali tidak ada; tiga arm ini membagi seluruh ruang nilaiOption<Option<u32>>tanpa sisa.
Mengabaikan Sebagian Isi Varian #
Ketika hanya sebagian data varian yang dibutuhkan, dua alat bantu siap dipakai: .. mengabaikan seluruh field varian bentuk struct, dan _ mengabaikan posisi tertentu pada varian bentuk tuple. Or-pattern | dapat menyatukan varian-varian yang perlakuannya sama, sepanjang setiap alternatif mengikat nama yang konsisten — varian tanpa binding seperti Message::Quit dan Message::Move { .. } aman digabung:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
fn summarize(message: Message) {
match message {
Message::Quit | Message::Move { .. } => println!("Pesan tanpa data yang perlu dicetak."),
Message::Write(text) => println!("Pesan: {}", text),
Message::ChangeColor(red, _, _) => println!("Komponen merah: {}", red),
}
}
fn main() {
summarize(Message::Quit);
summarize(Message::Move { x: 10, y: -4 });
summarize(Message::Write(String::from("Halo, Budi!")));
summarize(Message::ChangeColor(10, 200, 60));
}Output yang Dihasilkan:
Pesan tanpa data yang perlu dicetak.
Pesan tanpa data yang perlu dicetak.
Pesan: Halo, Budi!
Komponen merah: 10Mari kita uraikan pola-polanya:
- Baris 10 (
Message::Quit | Message::Move { .. } => ...): or-pattern menyatukan dua varian; polaMove { .. }memilih varianMovetanpa mengikatxdany, sehingga kedua varian dapat berbagi satu arm. - Baris 11 (
Message::Write(text) => ...): varian ini tetap mengikat isi teksnya karena isinya memang dibutuhkan — pengabaian dan pengikatan dapat berdampingan dalam satumatch. - Baris 12 (
Message::ChangeColor(red, _, _) => ...): hanya posisi pertama yang diikat menjadired; dua_mengabaikan komponen hijau dan biru. - Baris 16–17 (
summarize(Message::Quit); summarize(...)): dua varian berbeda —QuitdanMove— jatuh ke arm yang sama, terlihat dari dua baris keluaran pertama yang identik.
Kode yang Gagal: Jumlah Data Varian Salah #
Varian bentuk tuple menuntut pola dengan jumlah posisi yang persis sama dengan definisinya. Satu posisi kurang atau lebih langsung ditolak kompilator dengan galat E0023:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
fn main() {
let message = Message::ChangeColor(10, 200, 60);
match message {
Message::Quit => println!("Sesi diakhiri."),
Message::Move { x, y } => println!("Pindah ke ({}, {}).", x, y),
Message::Write(text) => println!("Pesan: {}", text),
Message::ChangeColor(r, g) => println!("Warna: rgb({}, {}).", r, g),
}
}Pesan error kompilator:
error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
--> main.rs:15:30
|
5 | ChangeColor(u8, u8, u8),
| -- -- -- tuple variant has 3 fields
...
15 | Message::ChangeColor(r, g) => println!("Warna: rgb({}, {}).", r, g),
| ^ ^ expected 3 fields, found 2
|
help: use `_` to explicitly ignore each field
|
15 | Message::ChangeColor(r, g, _) => println!("Warna: rgb({}, {}).", r, g),
| +++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0023`.Pesan error mengutip dua lokasi sekaligus: baris 5 tempat varian didefinisikan dengan tiga field, dan baris 15 tempat pola hanya memuat dua binding. Saran perbaikannya lugas — tambahkan _ untuk posisi yang tidak diperlukan. Aturan serupa berlaku pada varian bentuk struct: melupakan satu field pada pola Message::Move { x } memicu E0027 pattern does not mention field y, persis seperti pola struct biasa pada chapter sebelumnya.
Ringkasan #
Pola enum mengikuti bentuk varianya: varian tanpa data cukup path, varian struct diuraikan dengan field bernama, varian tuple diikat per posisi, dan lapisan enum di dalam enum diuraikan dengan pola bersarang. Posisi data dapat diisi literal untuk menguji isi, _ untuk mengabaikan, atau binding untuk memindahkan data ke arm. Or-pattern menyatukan varian-varian berperlakuan sama, dan jumlah data pola yang tidak sesuai definisi memicu E0023 lengkap dengan saran perbaikan. Chapter berikutnya menguraikan tipe komposit yang paling sederhana: tuple beserta pola posisinya.