کنترل جریان
Rust has a few control flow constructs which differ from other languages. They are used for pattern matching:
- عبارت
if let
let else
expressions- عبارت
while let
عبارت if let
The if let
expression lets you execute different code depending on whether a value matches a pattern:
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
expressions
For the common case of matching a pattern and returning from the function, use let else
. The “else” case must diverge (return
, break
, or panic - anything but falling off the end of the block).
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let s = if let Some(s) = maybe_string { s } else { return Err(String::from("got None")); }; let first_byte_char = if let Some(first_byte_char) = s.chars().next() { first_byte_char } else { return Err(String::from("got empty string")); }; if let Some(digit) = first_byte_char.to_digit(16) { Ok(digit) } else { Err(String::from("not a hex digit")) } } fn main() { println!("result: {:?}", hex_or_die_trying(Some(String::from("foo")))); }
Like with if let
, there is a while let
variant which repeatedly tests a value against a pattern:
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!) }
Here String::pop
returns Some(c)
until the string is empty, after which it will return None
. The while let
lets us keep iterating through all items.
if-let
- برخلاف دستور
match
دستورif let
همه حالت های ممکن را برای تطبیق الگو پشتیبانی نمیکند. اگر میخواهید همه حالت را پوشش دهید از دستورmatch
استفاده کنید. - یک استفاده رایج از دستور
if let
، رسیدگی به مقادیرSome
هنگام کار باOption
است: - برخلاف دستور
match
دستورif let
از=>
برای تطبیق الگو استفاده نمیکند.
let-else
if-let
s can pile up, as shown. The let-else
construct supports flattening this nested code. Rewrite the awkward version for students, so they can see the transformation.
The rewritten version is:
#![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("got None")); }; let Some(first_byte_char) = s.chars().next() else { return Err(String::from("got empty string")); }; let Some(digit) = first_byte_char.to_digit(16) else { return Err(String::from("not a hex digit")); }; return Ok(digit); } }
while-let
- توجه داشته باشید که حلقه
while let
تا زمانی که مقادیر مقابل الگو طبیق داشته باشد (شرط برقرار باشد)، ادامه خواهد داشت. - You could rewrite the
while let
loop as an infinite loop with an if statement that breaks when there is no value to unwrap forname.pop()
. Thewhile let
provides syntactic sugar for the above scenario.