زمینه استفاده از هر الگو
زبان Rust به ما اجازه نمیدهد که از هر الگویی در هر جایی استفاده کنیم. این محدودیت به کامپایلر
اجازه میدهد تا در زمان کامپایل، خطاهای منطقی را تشخیص دهد.
الگوهای ردناپذیر: let و حلقههای for
دستورات let، پارامترهای توابع و حلقههای for تنها میتوانند الگوهای ردناپذیر را بپذیرند.
دلیل این امر این است که این ساختارها برای مقادیر نامنطبق، هیچ راه بازگشتی یا رفتار جایگزینی
ندارند. اگر یک الگو در این زمینهها شکست بخورد، برنامه در یک وضعیت نامعتبر قرار میگیرد.
برای مثال، کد زیر کامپایل نخواهد شد:
src/main.rs
اگر some_option_value برابر با None باشد، الگوی Some(x) مطابقت پیدا نمیکند و برنامه
نمیداند چه کاری باید انجام دهد. کامپایلر Rust با جلوگیری از کامپایل این کد، ما را از این خطای
منطقی محافظت میکند.
الگوهای ردپذیر: match و if let
در مقابل، شاخههای یک عبارت match (به جز آخرین شاخه که باید تمام حالات باقیمانده را پوشش دهد)
و دستور if let، باید از الگوهای ردپذیر استفاده کنند. این ساختارها ذاتاً برای مدیریت شرایطی
طراحی شدهاند که یک الگو ممکن است مطابقت پیدا نکند و یک رفتار جایگزین برای آن تعریف شده است.
src/main.rs
let some_option_value: Option<i32> = None;
if let Some(x) = some_option_value {
println!("{}", x);
}
match some_option_value {
Some(x) => println!("{}", x),
None => (),
}
در هر دو عبارت if let و match، ما به صورت صریح حالتی را که الگو مطابقت پیدا نمیکند، مدیریت
کردهایم.
خلاصه
در این درس با تفاوت کلیدی بین الگوهای ردپذیر و ردناپذیر و اینکه هر کدام در چه زمینهای از زبان
Rust قابل استفاده هستند، آشنا شدیم. این تفکیک به کامپایلر اجازه میدهد تا در زمان کامپایل،
اطمینان حاصل کند که تمام حالات ممکن توسط کد ما پوشش داده شدهاند و از بروز خطاهای منطقی جلوگیری
میکند.
الگوها بسیار قدرتمندتر از چیزی هستند که تاکنون دیدهایم. در درس بعدی، به بررسی «تمام سینتکسهای
الگو» خواهیم پرداخت و با قابلیتهای پیشرفتهتری مانند تطبیق روی لیترالها، بازهها، و استفاده از
match guardها آشنا خواهیم شد.