Çürütülebilirlik: Bir Desenin Eşleşememe İhtimali
Desenler iki ana biçime ayrılır: çürütülebilir ve çürütülemez. Her olası
değerle eşleşen desenlere çürütülemez denir. Örneğin let x = 5;
ifadesindeki x böyledir; çünkü her şeyle eşleşir. Bazı olası değerlerde
eşleşmesi başarısız olabilen desenler ise _çürütülebilir_desendir. Örneğin
if let Some(x) = bir_deger ifadesindeki Some(x) böyledir; çünkü değer
None olursa desen eşleşmez.
Fonksiyon parametreleri, let ifadeleri ve for döngüleri yalnızca
çürütülemez desen kabul eder. Çünkü eşleşme başarısız olduğunda programın o
bağlamda anlamlı biçimde ne yapacağı belli değildir. if let, while let ve
let...else ise çürütülebilir desenlerle çalışmak için tasarlanmıştır.
Genelde bu ayrımı düşünmeniz gerekmez. Ama hata mesajlarında çürütülebilirlik karşınıza çıkınca, ya deseni ya da onu kullandığınız yapıyı değiştirmeniz gerektiğini anlamanız önemlidir.
Önce, çürütülebilir bir deseni let içinde kullanmaya çalıştığımız bir örneğe
bakalım. 19-8 numaralı liste bunu gösteriyor.
fn main() {
let bir_secenek_degeri: Option<i32> = None;
let Some(x) = bir_secenek_degeri;
}
let ile çürütülebilir desen kullanmaya çalışmakEğer bir_secenek_degeri, Some yerine None olsaydı, Some(x) deseni
eşleşemezdi. Ama let yalnızca çürütülemez desen kabul ettiği için derleyici
hata verir:
Checking desenler v0.1.0 (/home/hakanbiris/github/kitap/listings/ch19-patterns-and-matching/listing-19-08)
error[E0005]: refutable pattern in local binding
--> src/main.rs:4:9
|
4 | let Some(x) = bir_secenek_degeri;
| ^^^^^^^ 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/ch19-02-refutability.html
= note: the matched value is of type `Option<i32>`
help: you might want to use `let...else` to handle the variant that isn't matched
|
4 | let Some(x) = bir_secenek_degeri else { todo!() };
| ++++++++++++++++
For more information about this error, try `rustc --explain E0005`.
error: could not compile `desenler` (bin "desenler") due to 1 previous error
Sorun, Some(x) deseninin bütün olasılıkları kapsamamasıdır.
Eğer çürütülebilir bir desene gerçekten ihtiyacımız varsa, let yerine
let...else kullanabiliriz. Böylece desen eşleşmezse süslü parantez içindeki
kod çalışır. 19-9 numaralı liste bunu gösteriyor.
fn main() {
let bir_secenek_degeri: Option<i32> = None;
let Some(x) = bir_secenek_degeri else {
return;
};
}
let yerine let...else kullanmakBu biçimde desene bir çıkış yolu vermiş oluruz; desen eşleşmezse else
kolundaki kod devreye girer.
Ama bu kez de ters durum mümkündür: let...else içine zaten her zaman
eşleşecek bir desen koyarsanız, derleyici bunun anlamsız olduğunu söyler.
19-10 numaralı liste buna örnek:
fn main() {
let x = 5 else {
return;
};
}
let...else ile çürütülemez desen kullanmaya çalışmakBurada desen her zaman başarılı olduğu için else kolunun hiçbir anlamı kalmaz
ve Rust uyarı verir:
warning: irrefutable `let...else` pattern
--> src/main.rs:3:5
|
3 | let x = 5 else {
| ^^^^^^^^^
|
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
= note: `#[warn(irrefutable_let_patterns)]` on by default
warning: unused variable: `x`
--> src/main.rs:3:9
|
3 | let x = 5 else {
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
= note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
warning: `desenler` (bin "desenler") generated 2 warnings (run `cargo fix --bin "desenler" -p desenler` to apply 1 suggestion)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Bu nedenle match kolları genelde çürütülebilir desenler kullanır; son kol ise
genellikle kalan her şeyi yakalayan çürütülemez bir desen olur.
Artık desenlerin nerede kullanılabileceğini ve çürütülebilirlik ayrımını gördük. Sırada, desen oluştururken kullanabileceğimiz sözdizimlerinin tamamı var.