کنترل جریان Let
زبان Rust چند ساختار کنترل جریان دارد که با سایر زبانها متفاوت است. این ساختارها برای مطابقت الگو استفاده میشوند:
- عبارت
if let - عبارت
let else - عبارت
while let
عبارت if let
عبارت if let به شما امکان میدهد بسته به اینکه آیا یک مقدار با یک الگو مطابقت دارد، کدهای مختلفی را اجرا کنید:
use std::time::Duration; fn sleep_for(secs: f32) { if let Ok(dur) = Duration::try_from_secs_f32(secs) { std::thread::sleep(dur); println!("slept for {:?}", dur); } } fn main() { sleep_for(-10.0); sleep_for(0.8); }
عبارت let else
برای حالت رایج مطابقت با یک الگو و بازگشت از تابع، از let else استفاده کنید. در اینجا، حالت “else” باید منحرف شود (مانند return، break، یا panic - به غیر از اینکه از انتهای بلوک خارج شود).
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { if let Some(s) = maybe_string { if let Some(first_byte_char) = s.chars().next() { if let Some(digit) = first_byte_char.to_digit(16) { Ok(digit) } else { return Err(String::from("نه یک hex digit")); } } else { return Err(String::from("یک string خالی دریافت کردم")); } } else { return Err(String::from("هیچکدام")); } } fn main() { println!("نتیجه: {:?}", hex_or_die_trying(Some(String::from("foo")))); }
مانند if let، یک دستور while let وجود دارد که مقادیر مقابل الگو به طور مکرر (تکرار شوندهای) بررسی میکند:
fn main() { let mut name = String::from("Comprehensive Rust 🦀"); while let Some(c) = name.pop() { println!("character: {c}"); } // (There are more efficient ways to reverse a string!) }
در اینجا String::pop تا زمانی که رشته خالی نشده است، Some(c) را برمیگرداند و پس از آن None را باز میگرداند. استفاده از while let به ما این امکان را میدهد که به طور مداوم از میان همه موارد عبور کنیم.
if-let
- برخلاف دستور
matchدستورif letهمه حالت های ممکن را برای تطبیق الگو پشتیبانی نمیکند. اگر میخواهید همه حالت را پوشش دهید از دستورmatchاستفاده کنید. - یک استفاده رایج از دستور
if let، رسیدگی به مقادیرSomeهنگام کار باOptionاست. - برخلاف دستور
matchدستورif letاز=>برای تطبیق الگو استفاده نمیکند.
let-else
if-let ها میتوانند به صورت تو در تو انباشته شوند، همانطور که در اینجا نشان داده شده است. ساختار let-else از فلت کردن این کدهای تو در تو پشتیبانی میکند. نسخهی پیچیده را برای دانشآموزان بازنویسی کنید تا بتوانند تبدیل آن را مشاهده کنند.
نسخهی بازنویسی شده به صورت زیر است:
#![allow(unused)] fn main() { fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let Some(s) = maybe_string else { return Err(String::from("هیچکدام")); }; let Some(first_byte_char) = s.chars().next() else { return Err(String::from("یک string خالی دریافت کردم")); }; let Some(digit) = first_byte_char.to_digit(16) else { return Err(String::from("نه یک hex digit")); }; return Ok(digit); } }
while-let
- توجه داشته باشید که حلقه
while letتا زمانی که مقادیر مقابل الگو طبیق داشته باشد (شرط برقرار باشد)، ادامه خواهد داشت. - شما میتوانید حلقهی
while letرا به صورت یک حلقه بیپایان با یک دستورifبازنویسی کنید که در صورت عدم وجود مقداری برای باز کردن (unwrap) از()name.pop، شکسته میشود.while letیک Syntactic sugar برای این سناریو ارائه میدهد.