再帰関数は、自分自身を呼び出す関数です。
再帰関数には、少なくとも1つの_ベースケース_と、少なくとも1つの_再帰ケース_が必要です。
_ベースケース_は、関数を再び呼び出すことなく値を返します。_再帰ケース_は、いずれベースケースと一致するように入力を変えながら、関数を再び呼び出します。
多くの場合、それぞれのケースは別々の関数節に書きます。
# base case
def count([]), do: 0
# recursive case
def count([_head | tail]), do: 1 + count(tail)
鳥が大好きなバードウォッチャーで、毎日庭に何羽の鳥がやって来たかを記録しています。
せっかくなので、バードウォッチングを次のレベルに引き上げることにしました。データの記録と処理に役立つツールをいくつか実装することにしたのです。
データは整数の配列として保存することにしました。配列の最初の数値は今日庭に来た鳥の数、2番目は昨日の数、そのあとも同じように続きます。
BirdCount.today/1関数を実装しましょう。日々の鳥の数の配列を受け取り、今日の数を返すようにします。配列が空の場合は、nilを返します。
BirdCount.today([2, 5, 1])
# => 2
BirdCount.increment_day_count/1関数を実装しましょう。日々の鳥の数の配列を受け取り、今日の数を1増やします。配列が空の場合は、[1]を返します。
BirdCount.increment_day_count([4, 0, 2])
# => [5, 0, 2]
BirdCount.has_day_without_birds?/1関数を実装しましょう。日々の鳥の数の配列を受け取ります。庭に鳥が1羽も来なかった日が少なくとも1日あればtrueを、なければfalseを返します。
BirdCount.has_day_without_birds?([2, 0, 4])
# => true
BirdCount.has_day_without_birds?([3, 8, 1, 5])
# => false
BirdCount.total/1関数を実装しましょう。日々の鳥の数の配列を受け取り、データを集め始めてから庭に来た鳥の合計数を返します。
BirdCount.total([4, 0, 9, 0, 5])
# => 18
日によっては、ほかの日より忙しいこともあります。忙しい日とは、庭に5羽以上の鳥が来た日のことです。
BirdCount.busy_days/1関数を実装しましょう。日々の鳥の数の配列を受け取り、忙しかった日の数を返します。
BirdCount.busy_days([4, 5, 0, 0, 6])
# => 2