defmodule FightingSpirit do
def shout do
IO.puts "元氣ですかーーーッ!!!"
IO.puts "元氣があればなんでもできる!"
IO.puts "闘魂とは己に打ち克つこと。"
IO.puts "そして闘いを通じて己の魂を磨いていく"
IO.puts "ことだと思います。"
end
end
FightingSpirit.shout()
$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{闘魂とは己に打ち克つこと。}$
$\huge{そして闘いを通じて己の魂を磨いていく}$
$\huge{ことだと思います。}$
はじめに
Elixirの醍醐味である再帰関数。これはまさに猪木イズムの「道」のごとく、深く探求する価値があります。再帰関数を理解し使いこなすことで、Elixirのコードに闘魂を注ぎ込むことができます。本記事では、再帰関数の基本から応用までを、猪木さんの名言とともに解説します。
1. 再帰関数とは
「この道を行けばどうなるものか、危ぶむなかれ。危ぶめば道はなし。」
再帰関数の概念を恐れずに、一歩踏み出しましょう。
闘魂をもって、自らの道を切り開く勇気を持とう!
再帰関数とは、自身を呼び出すことで繰り返し処理を行う関数のことです。
基本的な再帰関数の例
基本的な再帰関数の例を示します。
例: 階乗の計算
階乗の計算例です。
defmodule Factorial do
def calculate(0), do: 1
def calculate(n) when n > 0 do
n * calculate(n - 1)
end
end
Factorial.calculate(5) # => 120
解説
-
calculate/1
関数は、n
が0の場合は1を返し、それ以外の場合はn * calculate(n - 1)
を計算します。 - これにより、5の階乗は
5 * 4 * 3 * 2 * 1 = 120
となります。
2. パターンマッチングとの組み合わせ
「出る前に負けること考える馬鹿いるかよ!」
複雑な処理も恐れずに挑戦しましょう。
挑戦することが、真の成長をもたらすのです!
再帰関数とパターンマッチングを組み合わせることで、より強力な処理が可能になります。
複雑な処理も恐れずに挑戦しましょう。
例: リスト内の特定の要素をカウント
リスト内の特定の要素をカウントする例です。
defmodule CountItem do
def count([], _item), do: 0
def count([item | tail], item), do: 1 + count(tail, item)
def count([_ | tail], item), do: count(tail, item)
end
CountItem.count([:red, :blue, :red, :green, :red], :red) # => 3
解説
- リストの先頭要素とカウントしたい
item
が一致する場合、1を加算します。 - 一致しない場合はそのまま再帰を続けます。
3. 再帰関数の応用
再帰関数を使ってさまざまなアルゴリズムを実装できます。
例: フィボナッチ数列
フィボナッチ数列を再帰で書いてみます。
defmodule Fibonacci do
def calc(0), do: 0
def calc(1), do: 1
def calc(n) when n > 1 do
calc(n - 1) + calc(n - 2)
end
end
Fibonacci.calc(10) # => 55
解説
- フィボナッチ数列を再帰的に計算しています。
- しかし、この方法は同じ計算を何度も行うため、効率的ではありません。
-
Fibonacci.calc(50)
くらいでなかなか計算が終わりません。
改善策
同じ計算を繰り返さないように、こんなやり方もあります。
defmodule Fibonacci do
def calc(n), do: fib(n, 0, 1)
defp fib(0, a, _), do: a
defp fib(n, a, b), do: fib(n - 1, b, a + b)
end
Fibonacci.calc(50) # => 12586269025
この実装では、計算済みの値を再利用することで、無駄な計算を省き効率的に結果を得ています。
50番目も即座に評価結果を得られます!
同じ道を何度も辿ることなく、一歩一歩確実に進むことで、大いなる目標に速やかに到達できるのです。
了解しました!では、もっと短いケーススタディの例を以下に示します。
ケーススタディ: フィボナッチ数列の計算
フィボナッチ数列は、再帰関数を使って簡単に計算できますが、効率性を考慮することが重要です。以下は、メモ化を使用したフィボナッチ数列の計算例です。
defmodule Fibonacci do
def calc(n), do: fib(n, %{})
defp fib(0, memo), do: {0, memo}
defp fib(1, memo), do: {1, memo}
defp fib(n, memo) do
case Map.get(memo, n) do
nil -> compute_fib(n, memo)
result -> {result, memo}
end
end
defp compute_fib(n, memo) do
{a, memo} = fib(n - 1, memo)
{b, memo} = fib(n - 2, memo)
result = a + b
new_memo = Map.put(memo, n, result)
{result, new_memo}
end
end
{result, _} = Fibonacci.calc(50) # => resultには12586269025が束縛されます
このように、再帰を用いて計算したフィボナッチ数列も、メモ化を活用することで効率的に結果を得ることができます。
どうやって実行するんだー!? バカヤローって方へ
GitHubのアカウントをお持ちの方へお手軽な方法を示しておきます。
PhoenixアプリケーションをGitHub Codespaces上で開発する方法で紹介したGitHub Codespacesを使うという方法です。
記事中で紹介しているphx_devcontainerを使うと、ElixirがインストールされたUbuntuコンテナが立ち上がるので、Ubuntu上で直接開発をしているかのように操作ができます。iex
コマンドでREPL(Read-Eval-Print Loop)が立ち上がるのでこの記事のコード例をぜひ試してください。
4. まとめ
再帰関数はElixirの強力なツールであり、効率的なアルゴリズムを実装する鍵となります。
再帰関数を使いこなすことでコードに闘魂を込めることができます。猪木さんの名言に励まされながら、恐れずに挑戦し続けましょう。
「道は自分で切り開くもの。再帰の道を極め、さらなる高みへと進もう!」
5. 次への一歩
「挑戦こそが未来を切り開く原動力である。」
- 再帰関数を使って独自のアルゴリズムを実装してみましょう。
- パターンマッチングを駆使して、複雑なデータ構造を操作する再帰関数を書いてみてください。
- メモ化や他の最適化手法を学び、効率的な再帰関数を目指しましょう。