何かをそれ自身で定義できることを、再帰と呼びます。F#では、再帰は再帰関数でよく見られます。再帰関数とは、自分自身を呼び出す関数のことです。
再帰関数には、少なくとも1つのベースケースと、少なくとも1つの再帰ケースが必要です。ベースケースは、関数を再び呼び出さずに値を返します。再帰ケースは、関数を再び呼び出し、入力に手を加えることで、いずれベースケースに一致するようにします。
再帰関数は通常の関数と同じように定義しますが、rec修飾子を付けます。この修飾子を付けないと、関数は自分自身を呼び出すことができません。呼び出そうとすると、コンパイルエラーになります。つまり、再帰を使うには明示的に指定する必要があります。
let rec factorial x =
// Base case
if x = 1 then
1
// Recursive case
else
x * factorial (x - 1)
F#では、判別共用体によって再帰的な型もサポートしています。再帰的な判別共用体では、1つ以上のケースが、そのデータの中で判別共用体自身を参照します。再帰関数と同じように、再帰的な型にもベースケースが必要です。再帰関数と違って、再帰的な型ではrecキーワードは使いません。
type RussianDoll =
| Doll // Base case
| Layer of RussianDoll // Recursive case
この演習では、お客さんに配達するピザ屋で働きます。
扱っているピザは、次の3種類です:
お客さんは、少額の追加料金を払うと、さらに2つのオプションも選べます:
お客さんが注文するとき、注文するピザが1枚か2枚だけだと、追加料金がかかります:
タスクは3つあり、どれもピザとその価格を扱います。
Pizzaという判別共用体を定義して、ピザの種類と、ピザに追加できる2つのオプションを表します:
MargheritaCapreseFormaggioExtraSauceExtraToppingspizzaPrice関数を実装して、ピザの価格を計算します:
pizzaPrice Caprese
// => 9
orderPrice関数を実装して、ピザの注文の価格を計算します:
orderPrice [Margherita; Formaggio]
// => 19