概要
関数型プログラミング(Functional Programming / FP)は、
副作用や状態を抑制し、より安全で予測可能なソフトウェア設計を志向する哲学だ。
この思想は単なるスタイルの違いではない。
それは「ソフトウェアの成長・保守・拡張に耐える設計」を根本から捉え直すための構造的転換である。
本稿では、FPの本質・背景・設計思想を整理しながら、Elixirでの事例を交えて解説する。
1. 命令型(Imperative)と関数型(Functional)の違い
✅ 命令型:「何をどうやるか」を記述
# Rubyでの命令型スタイル
total = 0
[1, 2, 3].each do |n|
total += n
end
puts total
- 状態(
total
)が変化しながらロジックが進行 - 実行順序に強く依存する
✅ 関数型:「何をしたいか」を記述
# Elixirでの関数型スタイル
IO.puts Enum.sum([1, 2, 3])
- 状態を持たず、式の合成で振る舞いを定義
- 実行順序に依存せず、副作用もない
2. なぜ今FPなのか?
✅ マルチスレッド時代の「安全性」を担保する
- 可変状態を持つ命令型コードはスレッドセーフでない
- FPはイミュータブル(不変)な値を基本とし、状態の競合を回避する
✅ テストしやすい構造を自然に得られる
- 関数が純粋(同じ入力 → 同じ出力)であれば
モック不要、DI不要、環境依存ゼロのテストが可能になる
✅ 副作用の制御が明示的になる
- IO / DB / ネットワークといった不可測な操作を明示的に分離できる
- 振る舞いの中心は「純粋なロジック」に留められる
3. 関数型の本質:構造としての「制約と自由」
特性 | 説明 |
---|---|
純粋関数 | 副作用を持たず、同じ入力には常に同じ出力を返す |
イミュータブル | 値の再代入ができず、全ての状態は新しい値として返る |
関数合成 | 小さな関数を繋げて大きな振る舞いを作る |
宣言的構文 | 処理の意図をコードで表現し、実行順序を持たない構造 |
4. Elixirにおける関数型思考の実践
純粋関数 + パターンマッチによる明快な設計
defmodule Tax do
def calc(:normal, price), do: price * 1.1
def calc(:reduced, price), do: price * 1.08
end
- 副作用なし
- 条件分岐も命令型の
if
ではなく、マッチングで表現 - データと振る舞いが分離されている
5. FPは「抽象化」のための構文ではなく、「思考の再設計」
❌ よくある誤解
-
FPは難解な構文の話?
→ No、それは結果であり本質ではない -
関数をいっぱい書くだけ?
→ No、副作用を排除し**“制御可能な世界”を作る思想**である
✅ 真のFPは「ロジックを透明にする設計哲学」
設計判断フロー
① この関数は副作用を含むか? → YES → 分離して外側に置く
② このデータは変化する必要があるか? → NO → イミュータブルで扱う
③ この構造は再利用しやすいか? → YES → 純粋関数 + 高階関数に昇華できる
④ 処理の意図を「何をしたいか」として記述できるか? → YES → 宣言的に書く
よくある疑問と答え
Q. FPは結局、実用に向いてるの?
✅ 向いてる。特に以下の分野で有効性が高い:
- 並行処理(Elixir / Erlang)
- ドメインロジックの抽象化(Haskell / Scala)
- ビジネスルールの表現力(F# / ReasonML)
- テストしやすさを設計で担保したい場面(TypeScript / Kotlin)
Q. JavaScriptやPythonでもFPできる?
✅ できる。
map
, filter
, reduce
などは関数型の片鱗。
状態・副作用を切り離すだけで、思想的にはほぼFPである。
結語
関数型プログラミングは、構文の美しさを追い求めるものではない。
それは、複雑さ・バグ・副作用・設計崩壊からソフトウェアを守る哲学である。
- 副作用を分離し、
- ロジックを構造化し、
- 実行ではなく意図を記述する
FPとは、
“予測不能な世界を、制御可能なロジックとして再構築するための抽象的な思考技術である。”