পাঠ ১৯.২

Refutability: Pattern fail করতে পারে কিনা

Refutability: Whether a Pattern Might Fail to Match

Pattern দু'ধরনের — refutable এবং irrefutable। যে pattern যেকোনো value-এর সাথে match করে, fail করার কোনো সম্ভাবনা নেই — সেটা irrefutable। যে pattern কিছু value-এর সাথে match নাও করতে পারে — সেটা refutable

দু'ধরনের উদাহরণ

let x = 5;-এ x একটা irrefutable pattern — যেকোনো value-ই x-এ bind করা যায়, fail করার সুযোগ নেই।

if let Some(x) = a_value-এ Some(x) refutable — a_value যদি None হয়, pattern match হবে না।

কে কোনটা accept করে

  • Function parameter, let statement, for loop — শুধু irrefutable। কারণ pattern fail করলে কী করবে এদের কাছে কোনো জবাব নেই।
  • if let, while let, let...else — refutable এবং irrefutable দু'টোই accept; কিন্তু irrefutable হলে compiler warning দেয় (কারণ এদের purpose-ই হলো success/failure-এ ভিন্ন behavior)।

সাধারণত এই distinction নিয়ে চিন্তা করতে হয় না — error message-এ term দু'টো দেখলে বুঝতে পারলেই হলো; তখন pattern বদলাও বা construct বদলাও।

let-এ refutable — error

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

some_option_value None হলে pattern Some(x) match হবে না — refutable। কিন্তু let চায় irrefutable। তাই compile error:

compile errortext
error[E0005]: refutable pattern in local binding
 --> 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/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
  |
3 |     let Some(x) = some_option_value else { todo!() };
  |                                     ++++++++++++++++

Compiler বলছে — None case cover হয়নি। Solution-এ hint দিচ্ছে let...else

let...else — fix

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

Pattern match না হলে else block চলবে — এখানে early return। Match হলে x bound, পরে use করা যায়।

let...else-এ irrefutable — warning

fn main() {
    let x = 5 else {
        return;
    };
}
warningtext
warning: irrefutable `let...else` pattern
 --> src/main.rs:2:5
  |
2 |     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

Pattern সবসময় match করবে — else অর্থহীন। Warning, error না।

match-এর arm

match-এর arm — refutable pattern হতে হবে, শেষ arm ছাড়া (যেটা irrefutable হিসেবে remaining সব value cover করে)। Rust-এ এক arm-ের match irrefutable-এ allowed, কিন্তু সেটা সরাসরি let-ই হতো — তাই খুব useful না।

এই পাঠ থেকে যা শিখলে

  • Irrefutable — সবসময় match; refutable — কখনো fail করতে পারে।
  • let, function parameter, for — irrefutable চায়।
  • if let, while let, let...else — দু'টোই accept; কিন্তু irrefutable-এ warning।
  • Refutable pattern let-এ ঢোকাতে চাইলে — let...else ব্যবহার।