関数型プログラミング かんすうがたぷろぐらみんぐ
純粋関数イミュータブル副作用高階関数ラムダ式宣言的プログラミング
関数型プログラミングについて教えて
簡単に言うとこんな感じ!
料理レシピを「手順書」じゃなく「材料と完成形の定義」で書くイメージだよ!「データを変更する」じゃなく「データを受け取って新しいデータを返す」という考え方でプログラムを組むスタイルなんだ。副作用が少なくバグが減るってこと!
関数型プログラミングとは
関数型プログラミング(Functional Programming、FP) とは、「関数」を中心にプログラムを組み立てるプログラミングのスタイル(パラダイム)です。ここでいう「関数」とは数学的な意味の関数——同じ入力には必ず同じ出力が返り、外部の状態を変えない——を指します。
従来の命令型プログラミングが「コンピュータに手順を指示する」書き方であるのに対し、関数型プログラミングは「何を計算するか」を宣言的に記述します。データを直接書き換えない(イミュータブル)・副作用をなくす(純粋関数) という原則を守ることで、コードの予測しやすさ・テストのしやすさが格段に上がります。
近年はJavaScript・Python・Kotlinなど主流言語にも関数型の機能が取り込まれており、「完全に関数型で書く」場面よりも「関数型のエッセンスを活用する」形で実務に浸透しています。特に並列処理・データパイプライン・フロントエンド設計の分野で存在感を増しています。
関数型プログラミングの核心的な4つの原則
| 原則 | 意味 | 具体例 |
|---|---|---|
| 純粋関数 | 同じ入力→同じ出力。外部状態を変えない | add(2, 3) は常に 5 |
| イミュータブル | データを書き換えず、新しいデータを作る | 配列を変更せずコピーして返す |
| 高階関数 | 関数を引数・戻り値に使える | map, filter, reduce |
| 副作用の分離 | DBアクセス・I/Oなど「外への影響」を端に追い出す | Pure Coreパターン |
命令型 vs 関数型:同じ処理を比べてみよう
【命令型(手順を指示)】
let total = 0
for (let i = 0; i < prices.length; i++) {
if (prices[i] > 100) {
total += prices[i]
}
}
【関数型(何を計算するかを宣言)】
const total = prices
.filter(p => p > 100)
.reduce((acc, p) => acc + p, 0)
関数型の方が「何をしているか」が一目で読み取れます。
覚え方:「純粋関数=約束を守る友人」
純粋関数は「同じ質問には必ず同じ答えを返す、外で余計なことをしない」友人のようなもの。 裏で勝手にグローバル変数を書き換えたりしない——だから信頼できる!
歴史と背景
- 1930年代 — アロンゾ・チャーチがラムダ計算を考案。関数型プログラミングの数学的基盤が生まれる
- 1958年 — John McCarthyがLISPを開発。史上初の実用的関数型言語
- 1973年 — MLが登場。型推論・パターンマッチングなど現代FPの原型が揃う
- 1987年 — Haskellの設計が開始(1990年公開)。純粋関数型言語の代表格に
- 1996年 — Erlangが公開。並列処理・耐障害性に強く通信インフラで活躍
- 2003年 — Scala登場。JVM上でオブジェクト指向+関数型を融合
- 2012年 — Elm・Elixir登場。WebフロントエンドとWeb APIに関数型が進出
- 2015年〜 — JavaScript(ES6)・Java 8・Kotlin・Swiftなど主流言語が
map/filter/ラムダを標準搭載。FPが「一部の人のもの」から「全員のもの」へ
プログラミングパラダイムの全体像と関数型の位置づけ
関数型 vs 命令型:特徴の比較
| 観点 | 命令型 | 関数型 |
|---|---|---|
| 基本の単位 | 文(Statement) | 式(Expression) |
| データの扱い | 変数を書き換える | 新しい値を作る |
| ループ | for / while | map / reduce / 再帰 |
| 状態管理 | グローバル・クラス変数 | 引数と戻り値で受け渡す |
| テストのしやすさ | 環境依存で難しいことも | 純粋関数なら容易 |
| 並列処理 | 競合状態に注意が必要 | イミュータブルなので安全 |
主要な関数型言語・ライブラリの現在地
| 言語/ライブラリ | 特徴 | 主な用途 |
|---|---|---|
| Haskell | 純粋関数型の代表。型システムが強力 | 研究・金融・コンパイラ開発 |
| Erlang / Elixir | 並列処理・耐障害性に特化 | 通信インフラ・Web API |
| Scala | Java互換。FP+OOP | ビッグデータ(Spark) |
| Elm | WebフロントエンドのFP専用言語 | SPA開発 |
| React(JS) | FPの考え方をUI設計に応用 | Webフロントエンド |
| RxJS / ReactiveX | ストリーム処理をFPスタイルで | イベント駆動処理 |
関連用語
- ./050-imperative-programming.md — 命令型プログラミング:手順を1ステップずつ指示する伝統的なスタイル
- ./051-object-oriented-programming.md — オブジェクト指向プログラミング:データと処理を「オブジェクト」としてまとめるパラダイム
- ./053-lambda-expression.md — ラムダ式:名前を持たない無名関数を簡潔に書く構文
- ./054-immutability.md — イミュータブル:一度作ったデータを変更しないという設計原則
- ./055-higher-order-function.md — 高階関数:関数を引数や戻り値として扱える関数(map・filter・reduceなど)
- ./056-pure-function.md — 純粋関数:同じ入力に必ず同じ出力を返し副作用を持たない関数
- ./057-reactive-programming.md — リアクティブプログラミング:データストリームの変化に反応して処理を行うスタイル
- ./058-declarative-programming.md — 宣言的プログラミング:「どうやるか」でなく「何がほしいか」を記述するスタイル