کنترل جریان 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 برای این سناریو ارائه میدهد.