Pola rentang seperti 90..=100 menguji keanggotaan nilai, tetapi pola tersebut tidak menyimpan nilai yang lolos uji — arm harus membaca ulang variabel luar di badannya bila nilai itu ingin dipakai. Match guard dengan pengikatan (s if s >= 90 && s <= 100) menyelesaikan setengah masalah, namun menulis rentang sebagai dua perbandingan terasa dikerjakan dua kali. Operator @ menyatukan keduanya: pola s @ 90..=100 menguji rentang dan mengikat nilai yang cocok ke s dalam satu penulisan. Chapter ini membahas @ pada rentang, pada field varian enum, pada pengikatan nilai utuh bersama bagiannya, serta interaksinya dengan or-pattern yang menuntut tanda kurung.
Mengikat Nilai yang Lolos Uji Rentang #
Bentuk dasarnya adalah binding @ pola — nama variabel di kiri operator @, pola pengujian di kanannya. Kompilator mencocokkan nilai dengan pola di sisi kanan; apabila cocok, nilai yang sama diikat ke variabel di sisi kiri. Contoh berikut memetakan skor ujian ke predikat sambil tetap menyimpan skornya:
fn main() {
let score = 84;
match score {
s @ 90..=100 => println!("Skor {} berpredikat A.", s),
s @ 80..=89 => println!("Skor {} berpredikat B.", s),
s @ 70..=79 => println!("Skor {} berpredikat C.", s),
s @ 0..=69 => println!("Skor {} mengulang materi.", s),
_ => println!("Skor {} tidak sah.", score),
}
}Output yang Dihasilkan:
Skor 84 berpredikat B.Mari kita bedah kode di atas:
- Baris 5 (
s @ 90..=100 => ...): nilai dibandingkan dengan rentang90..=100; apabila lolos, nilai tersebut diikat kes— arm ini tidak cocok untuk84, sehingga pencocokan turun. - Baris 6 (
s @ 80..=89 => ...): rentang80..=89menerima84, danslangsung berisi84; badan arm mencetak skor tanpa membaca variabelscoredi luarmatch. - Baris 7–8 (
s @ 70..=79dans @ 0..=69): pola@yang sama berulang untuk dua rentang berikutnya — setiap arm mandiri dengan bindingnya sendiri. - Baris 9 (
_ => println!("Skor {} tidak sah.", score);): wildcard tidak mengikat apa pun, sehingga nilai tidak sah dilaporkan lewat variabel luarscore— perbedaan ini menegaskan bahwa@adalah pengikatan, bukan sekadar pengujian.
Nilai i32 bersifat Copy, sehingga s menerima salinan skor dan variabel score tetap sah. Untuk data non-Copy, pengikatan @ mengikuti aturan kepemilikan yang berlaku pada pola biasa — pokok ini muncul kembali di bagian akhir chapter.
Mengikat Field Varian dengan @ #
Operator @ dapat ditempatkan pada posisi pola mana pun, termasuk field varian enum. Pola seat: s @ 1..=100 menguji field seat terhadap rentang sekaligus menyimpan nilainya ke s. Contoh berikut membagi area kursi berdasarkan nomornya:
enum Ticket {
Vip { seat: u16 },
Regular { seat: u16 },
}
fn main() {
let tickets = [Ticket::Vip { seat: 411 }, Ticket::Regular { seat: 85 }];
for ticket in tickets {
match ticket {
Ticket::Vip { seat: s @ 1..=100 } => println!("VIP depan, kursi {}.", s),
Ticket::Vip { seat: s @ 101..=500 } => println!("VIP tengah, kursi {}.", s),
Ticket::Vip { seat } => println!("VIP belakang, kursi {}.", seat),
Ticket::Regular { seat } => println!("Regular, kursi {}.", seat),
}
}
}Output yang Dihasilkan:
VIP tengah, kursi 411.
Regular, kursi 85.Mari kita uraikan polanya:
- Baris 11 (
Ticket::Vip { seat: s @ 1..=100 } => ...): pola field memakai bentukfield: binding @ rentang— kursi VIP diuji terhadap1..=100dan hasilnya diikat kesbila lolos. - Baris 12 (
Ticket::Vip { seat: s @ 101..=500 } => ...): rentang kedua menangkap nomor411; bindingskembali memuat nilai yang cocok sehingga nomor kursi tercetak tanpa pengikatan terpisah. - Baris 13 (
Ticket::Vip { seat } => ...): arm penampung varianViptanpa rentang — kursi VIP di atas500diikat langsung olehseat. - Baris 14 (
Ticket::Regular { seat } => ...): varianRegularmemiliki pola field biasa; tiket kedua jatuh ke arm ini dan mencetak kursi85.
Urutan arm kembali menentukan hasil: tiga arm Vip tersusun dari rentang paling awal hingga penampung terbuka, sehingga setiap nomor kursi menemukan arm yang tepat sebelum wildcard varian mana pun terlibat.
Mengikat Nilai Utuh dan Bagian Dalamnya #
Operator @ juga dapat mengikat seluruh nilai yang dicocokkan sementara pola di kanannya menguraikan bagian dalamnya. Pola s @ Some(qty) memeriksa varian Some, mengikat isi ke qty, dan mengikat nilai Option utuh ke s. Dikombinasikan dengan guard dari chapter match Lanjutan, satu arm dapat mengambil keputusan dari bagian dalam sekaligus melaporkan keadaan utuhnya:
fn main() {
let stock: Option<u32> = Some(12);
match stock {
s @ Some(0) => println!("Nilai {:?} berarti stok habis.", s),
s @ Some(qty) if qty <= 20 => println!("Nilai {:?} berarti stok tipis.", s),
s @ Some(_) => println!("Nilai {:?} berarti stok aman.", s),
s @ None => println!("Nilai {:?} berarti tidak dilacak.", s),
}
}Output yang Dihasilkan:
Nilai Some(12) berarti stok tipis.Mari kita bedah keempat armnya:
- Baris 5 (
s @ Some(0) => ...):smengikat nilaiOptionutuh, sementaraSome(0)menguji varian dan isinya — arm ini hanya cocok untukSome(0)tepat; penanda{:?}mencetak bentuk Debug dari nilai utuh. - Baris 6 (
s @ Some(qty) if qty <= 20 => ...): tiga mekanisme bekerja sekaligus —smengikat nilai utuh,qtymengikat isiSome, dan guard menguji isi terhadap20; nilaiSome(12)lolos ketiganya sehingga arm ini terpilih. - Baris 7 (
s @ Some(_) => ...): varianSomediuji tanpa mengikat isinya (_), nilai utuh tetap masuk kes— arm ini menjadi penampung stok di atas20. - Baris 8 (
s @ None => ...): varianNonediikat utuh kes, menggenapi cakupan seluruh kemungkinanOption<u32>.
Pada contoh di atas Option<u32> bersifat Copy sehingga pengikatan ganda tidak menimbulkan masalah kepemilikan. Untuk data non-Copy, mengikat nilai utuh dengan @ sekaligus mengikat bagian dalamnya by value akan ditolak kompilator dengan galat E0382 use of partially moved value — nilai tidak dapat dipindahkan dua kali ke dua binding berbeda. Solusinya adalah meminjam salah satunya dengan ref, teknik yang dibahas tuntas pada chapter berikutnya.
@ Bersama Or-Pattern #
Operator @ memiliki aturan penulisan khusus ketika pola di kanannya memuat or-pattern. Tanpa tanda kurung, r @ 1 | 2 terbaca sebagai (r @ 1) | 2 — pengikatan r hanya melekat pada alternatif pertama. Kompilator menolak ketidakseimbangan ini:
fn main() {
let rating = 4;
match rating {
r @ 1 | 2 => println!("Rating rendah: {}.", r),
_ => println!("Rating lainnya."),
}
}Pesan error kompilator:
error[E0408]: variable `r` is not bound in all patterns
--> main.rs:5:17
|
5 | r @ 1 | 2 => println!("Rating rendah: {}.", r),
| - ^ pattern doesn't bind `r`
| |
| variable not in all patterns
error[E0381]: used binding `r` is possibly-uninitialized
--> main.rs:5:53
|
5 | r @ 1 | 2 => println!("Rating rendah: {}.", r),
| - ^ `r` used here but it is possibly-uninitialized
| |
| binding initialized here in some conditions
| binding declared here but left uninitialized
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0381, E0408.
For more information about an error, try `rustc --explain E0381`.Dua galat ini saling melengkapi: E0408 menyatakan bahwa variabel r tidak terikat pada semua alternatif — alternatif 2 tidak mengikat apa pun — dan E0381 menyusul karena badan arm memakai r yang mungkin tidak pernah terisi saat alternatif kedua yang terpilih. Perbaikannya adalah membungkus or-pattern dengan tanda kurung sehingga @ mengikat hasil seluruh kelompok:
fn main() {
let rating = 2;
match rating {
r @ (1 | 2) => println!("Rating rendah: {}.", r),
_ => println!("Rating lainnya."),
}
}Output yang Dihasilkan:
Rating rendah: 2.Pada baris 5, pola r @ (1 | 2) kini utuh: nilai dibandingkan dengan or-pattern (1 | 2), dan nilai yang cocok — baik 1 maupun 2 — masuk ke r; nilai 2 pada program ini tercetak sebagai isi r.
Ringkasan #
Operator @ menjodohkan pengujian dan pengikatan: s @ 90..=100 menguji rentang dan menyimpan nilai yang cocok, seat: s @ 1..=100 menerapkannya pada field varian, dan s @ Some(qty) mengikat nilai utuh sekaligus bagiannya. Pengikatan @ mengikuti aturan kepemilikan — aman untuk tipe Copy, dan memerlukan ref ketika nilai utuh dan bagiannya sama-sama ingin dipegang pada data non-Copy. Bersama or-pattern, @ menuntut tanda kurung; tanpanya E0408 dan E0381 menandai pengikatan yang tidak merata. Chapter berikutnya membahas ref dan ref mut yang membuat pola mampu meminjam data tanpa mengambil kepemilikannya.