به توانایی تعریف شدن یک چیز بر حسب خودش، «بازگشت» میگویند. در F#، بازگشت بیشتر در قالب توابع بازگشتی دیده میشود؛ توابعی که خودشان را فراخوانی میکنند.
یک تابع بازگشتی باید حداقل یک «حالت پایه» و حداقل یک «حالت بازگشتی» داشته باشد. حالت پایه بدون فراخوانی دوبارهی تابع، یک مقدار برمیگرداند. حالت بازگشتی تابع را دوباره فراخوانی میکند و ورودی را طوری تغییر میدهد که در نقطهای با حالت پایه مطابقت کند.
توابع بازگشتی مانند توابع معمولی تعریف میشوند، اما با اصلاحکنندهی rec. بدون این اصلاحکننده، یک تابع نمیتواند خودش را فراخوانی کند و هر تلاشی برای این کار به یک خطای کامپایل منجر میشود. بنابراین بازگشت باید صریحاً انتخاب شود.
let rec factorial x =
// Base case
if x = 1 then
1
// Recursive case
else
x * factorial (x - 1)
F# همچنین از انواع بازگشتی از طریق اتحادهای تفکیکشده پشتیبانی میکند. در یک نوع اتحاد تفکیکشدهی بازگشتی، دادهی یک یا چند حالت به خود آن نوع ارجاع میدهد. مانند توابع بازگشتی، انواع بازگشتی هم باید یک حالت پایه داشته باشند. برخلاف توابع بازگشتی، انواع بازگشتی از کلیدواژهی rec استفاده نمیکنند.
type RussianDoll =
| Doll // Base case
| Layer of RussianDoll // Recursive case
در این تمرین، در یک پیتزافروشی کار میکنید که پیتزا به مشتریان تحویل میدهد.
سه نوع پیتزا ارائه میدهید:
مشتریان میتوانند دو گزینهی اضافی دیگر را هم با پرداخت هزینهی کمی انتخاب کنند:
وقتی مشتریان سفارش میدهند، اگر فقط یک یا دو پیتزا سفارش دهند، هزینهی اضافی به سفارش اضافه میشود:
سه کار دارید که هر کدام با پیتزا و قیمت آن سروکار دارد.
«اتحاد تفکیکشدهی Pizza» را تعریف کنید تا انواع پیتزا و دو گزینهی اضافی را که میتوان به یک پیتزا افزود، نمایش دهد:
MargheritaCapreseFormaggioExtraSauceExtraToppingsتابع pizzaPrice را پیادهسازی کنید تا قیمت یک پیتزا را محاسبه کند:
pizzaPrice Caprese
// => 9
تابع orderPrice را پیادهسازی کنید تا قیمت یک سفارش پیتزا را محاسبه کند:
orderPrice [Margherita; Formaggio]
// => 19