Reddedilebilirlik: Bir Model; Eşleşmede Başarısız Olabilir mi?

Modeller iki biçimde gelir: reddedilebilir ve reddedilemez. Geçilen herhangi bir olası değer için eşleşecek kalıplar reddedilemez. Bir örnek, let x = 5 ifade yapısındaki x olabilir; çünkü x herhangi bir şeyle eşleşir ve bu nedenle eşleşme başarısız olamaz. Bazı olası değerler için eşleşmeyen kalıplar reddedilebilir.

Fonksiyon parametreleri, let deyimleri ve for döngüleri yalnızca reddedilemez kalıpları kabul edebilir, çünkü değerler eşleşmediğinde program anlamlı bir şey yapamaz. if let ve while let ifadeleri reddedilemez ve reddedilemez modelleri kabul eder, ancak derleyici reddedilemez kalıplara karşı uyarır çünkü tanımları gereği olası başarısızlığı ele almayı amaçlarlar: bir koşulun işlevselliği, başarıya veya başarısızlığa bağlı olarak farklı performans gösterme yeteneğindedir.

Genel olarak, reddedilebilir ve reddedilemez modeller arasındaki ayrım hakkında endişelenmenize gerek yoktur; ancak, bir hata mesajında gördüğünüzde yanıt verebilmeniz için reddedilebilirlik kavramına aşina olmanız gerekir. Bu durumlarda, kodun amaçlanan davranışına bağlı olarak, modeli veya modeli kullandığınız yapıyı değiştirmeniz gerekir.

Rust'ın reddedilemez bir model gerektirdiği ve bunun tersi olduğu halde, çürütülebilir bir model kullanmaya çalıştığımızda ne olduğuna dair bir örneğe bakalım. Liste 18-8, bir let ifade yapısını gösterir, ancak Some(x) belirttiğimiz model için reddedilebilir bir modeldir. Tahmin edebileceğiniz gibi, bu kod derlenmeyecektir:

fn main() {
    let some_option_value: Option<i32> = None;
    let Some(x) = some_option_value;
}

Liste 18-8: let ile çürütülebilir bir model kullanmaya çalışmak

some_option_value, None değerinde olsaydı, Some(x) modeliyle eşleşmezdi, bu da kalıbın reddedilebilir olduğu anlamına gelir. Ancak, let ifade yapısı yalnızca reddedilemez bir kalıbı kabul edebilir, çünkü kodun None değeriyle yapabileceği geçerli hiçbir şey yoktur. Derleme zamanında; Rust, reddedilemez bir modelin gerekli olduğu durumlarda reddedilebilir bir model kullanmaya çalıştığımızdan şikayet edecektir:

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0005]: refutable pattern in local binding: `None` not covered
   --> src/main.rs:3:9
    |
3   |     let Some(x) = some_option_value;
    |         ^^^^^^^ pattern `None` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
    |
3   |     if let Some(x) = some_option_value { /* */ }
    |

For more information about this error, try `rustc --explain E0005`.
error: could not compile `patterns` due to previous error

Some(x) modeliyle geçerli her değeri kapsamadığımız (ve kapsayamadığımız) için, Rust haklı olarak bir derleyici hatası üretir.

Çürütülemez bir modele ihtiyaç duyulan bir çürütülebilir modelimiz varsa, modeli kullanan kodu değiştirerek düzeltebiliriz: let yerine if let kullanabiliriz. Ardından, model eşleşmezse, kod, süslü parantezler arasındaki kodu atlayarak geçerli bir şekilde devam etmesinin bir yolunu sunar. Liste 18-9, Liste 18-8'deki kodun nasıl düzeltileceğini gösterir.

fn main() {
    let some_option_value: Option<i32> = None;
    if let Some(x) = some_option_value {
        println!("{}", x);
    }
}

Liste 18-9: let yerine if let kullanan ve reddedilebilir modellere sahip bir blok kullanma

Kodu bir çıkış verdik! Bu kod tamamen geçerlidir, ancak bir hata almadan reddedilemez bir model kullanamayacağımız anlamına gelir. Liste 18-10'da gösterildiği gibi x gibi her zaman eşleşecek bir model verirsek, derleyici bir uyarı verecektir.

fn main() {
    if let x = 5 {
        println!("{}", x);
    };
}

Liste 18-10: if let ile reddedilemez bir model kullanmaya çalışmak

Rust, reddedilemez bir modelle if let kullanmanın mantıklı olmadığından şikayet ediyor:

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
warning: irrefutable `if let` pattern
 --> src/main.rs:2:8
  |
2 |     if let x = 5 {
  |        ^^^^^^^^^
  |
  = note: `#[warn(irrefutable_let_patterns)]` on by default
  = note: this pattern will always match, so the `if let` is useless
  = help: consider replacing the `if let` with a `let`

warning: `patterns` (bin "patterns") generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/patterns`
5

Bu nedenle, eşleşme kolları, kalan değerleri reddedilemez bir modelle eşleştirmesi gereken son kol hariç, reddedilebilir modeller kullanmalıdır. Rust, tek kollu bir eşleşmede reddedilemez bir model kullanmamıza izin verir, ancak bu söz dizimi çok kullanışlı değildir ve daha basit bir let ifade yapısı ile değiştirilebilir.

Artık modeleri nerede kullanacağınızı ve reddedilebilir ve reddedilemez modeller arasındaki farkı bildiğinize göre, model oluşturmak için kullanabileceğimiz söz dizimini ele alalım.