تط

تطبیق الگو در F#

1 تمرین

درباره‌ی تطبیق الگو

از یک عبارت if/elif/else می‌توان برای اجرای منطق به‌صورت شرطی استفاده کرد. F# روش قدرتمندتر دیگری هم برای اجرای شرطی منطق دارد: تطبیق الگو. با تطبیق الگو می‌توان یک مقدار را در برابر یک یا چند الگو آزمایش کرد. نمونه‌ای از چنین الگویی الگوی ثابت است که یک مقدار را با یک ثابت (مثلاً 1 یا "hello") مطابقت می‌دهد.

در F#، تطبیق الگو با کلیدواژه‌ی match انجام می‌شود:

let describe number =
    match number with
    | 0 -> "Zero"
    | 1 -> "One"

هرچند این ممکن است شبیه دستورهای switch در زبان‌های دیگر به نظر برسد، تطبیق الگو وقتی از الگوهای دیگر هم استفاده می‌کنید تازه خودش را نشان می‌دهد. یکی از این الگوها الگوی متغیر است که امکان ثبت یک مقدار را فراهم می‌کند:

match number with
| 0 -> "Zero"
| i -> sprintf "Non zero: %d" i

در بعضی موارد، ممکن است بخواهید شرط دیگری به یک الگو اضافه کنید. به این کار گارد (بند) می‌گویند که با کلیدواژه‌ی when اضافه می‌شود:

match number with
| 0 -> "Zero"
| i when i < 0 -> "Negative number"

یک بند گارد می‌تواند هر عبارت معتبری باشد، از جمله فراخوانی توابع.

در مثال بالا، همه‌ی ورودی‌های ممکن الگوی متناظر ندارند. کامپایلر این را تشخیص می‌دهد و هشداری می‌دهد. به این کار تطبیق جامع می‌گویند. برای رفع این هشدار باید همه‌ی حالت‌ها را پوشش داد. برای این کار می‌توان از [الگوی عام][wildcard-pattern] استفاده کرد که با هر مقداری مطابقت می‌کند:

match number with
| i when i < 0 -> "Negative number"
| _ -> "Positive number"

// No compiler warning

توجه داشته باشید که کامپایلر نمی‌تواند از بندهای when برای استنباط جامع بودن استفاده کند:

match number with
| i when i < 0 -> "Negative number"
| i when i >= 0 -> "Positive number"

// Compiler warning

تطبیق الگو یک مقدار را از بالا به پایین با هر الگو آزمایش می‌کند، تا اینکه الگوی متناظر را پیدا کند و منطق مرتبط با آن الگو را اجرا کند. ترتیب الگوها مهم است! بنابراین الگوی نادیده‌گرفتن همیشه باید آخرین الگو در یک عبارت match باشد.

با اینکه تطبیق الگو بسیار قدرتمند است، منطق شرطی ساده معمولاً با یک عبارت if/else واضح‌تر بیان می‌شود:

let usingPatternMatching number =
    match number with
    | 0 -> "Zero"
    | _ -> "Non-zero"

let usingIfElse number = if number = 0 then "Zero" else "Non-zero"
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

تطبیق الگو را یاد بگیرید