این تبدیلها (Conversions) را امتحان کنید
گسترش مؤثر ?
کمی پیچیدهتر از آنچه قبلاً ذکر شد است:
expression?
به طو مشابه کار میکند
match expression {
Ok(value) => value,
Err(err) => return Err(From::from(err)),
}
فراخوانی From::from
در اینجا به این معنی است که ما سعی می کنیم نوع خطا را به نوع بازگشتی توسط تابع تبدیل کنیم. این باعث میشود که خطاها به خطاهای سطح بالاتر کپسوله شوند.
مثال
use std::error::Error; use std::fmt::{self, Display, Formatter}; use std::fs::File; use std::io::{self, Read}; #[derive(Debug)] enum ReadUsernameError { IoError(io::Error), EmptyUsername(String), } impl Error for ReadUsernameError {} impl Display for ReadUsernameError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Self::IoError(e) => write!(f, "IO error: {e}"), Self::EmptyUsername(path) => write!(f, "در این {path} نام کاربری یافت نشد"), } } } impl From<io::Error> for ReadUsernameError { fn from(err: io::Error) -> Self { Self::IoError(err) } } fn read_username(path: &str) -> Result<String, ReadUsernameError> { let mut username = String::with_capacity(100); File::open(path)?.read_to_string(&mut username)?; if username.is_empty() { return Err(ReadUsernameError::EmptyUsername(String::from(path))); } Ok(username) } fn main() { //std::fs::write("config.dat", "").unwrap(); let username = read_username("config.dat"); println!("نامکاربری یا خطا: {username:?}"); }
عملگر ?
باید مقداری سازگار با نوع بازگشتی تابع برگرداند. برای Result
، به این معنی است که انواع خطا باید سازگار باشند. تابعی کهResult<T, ErrorOuter>
را برمیگرداند، تنها میتواند از ?
در مقداری از تایپهای Result<U, ErrorInner>
استفاده کند اگر ErrorOuter
و ErrorInner
یک نوع باشند یا اگر ErrorOuter
از
یک جایگزین رایج برای پیاده سازی From
جهت Result::map_err
است، به خصوص زمانی که تبدیلها فقط در یک مکان انجام میشود.
هیچ الزامی برای سازگاری Option
وجود ندارد. تابعی که Option<T>
را برمی گرداند می تواند از عملگر ?
در Option<U>
برای انواع دلخواه T
و U
استفاده کند.
یک تابعی که Result
را برمیگرداند دیگر نمیتواند از ?
در Option
استفاده کند و بالعکس. با اینحال، Option::ok_or
یک Option
را به Result
تبدیل میکند در حالی که Result::ok
«نتیجه» را به Option
تبدیل میکند.