高階関数 こうかいかんすう
関数型プログラミングコールバックラムダ式map/filter/reduceクロージャ第一級関数
高階関数について教えて
簡単に言うとこんな感じ!
「関数を引数として受け取ったり、関数を返したりできる関数」のことだよ!料理レシピ(関数)を別のレシピに渡して「この手順でやって!」と指示するイメージ。コードを部品化して使い回しやすくする、現代プログラミングの重要テクニックなんだ!
高階関数とは
高階関数(Higher-Order Function)とは、「関数を引数として受け取る」または「関数を戻り値として返す」、あるいはその両方を行う関数のことです。これは関数型プログラミングの中核的な概念のひとつで、JavaScriptやPython、Scalaなど多くのモダンな言語で広くサポートされています。
高階関数が成り立つ前提として、第一級関数(First-Class Function)という性質が必要です。第一級関数とは、関数を数値や文字列と同じように「値」として扱える性質のこと。変数に代入したり、引数に渡したり、戻り値にしたりが自由にできる状態です。この性質があって初めて「関数を関数に渡す」という高階関数の操作が可能になります。
実務では、コールバック関数(処理が終わったら呼び出してほしい関数)や、配列操作のmap・filter・reduceといった形で日常的に登場します。コードの重複を減らし、処理の「骨格」と「中身」を分離できるため、保守しやすいソフトウェア設計の武器になります。
高階関数の3つのパターン
| パターン | 説明 | 具体的な例 |
|---|---|---|
| 関数を引数に取る | 処理の一部を外から差し込める | array.map(fn) / setTimeout(fn, ms) |
| 関数を返す | カスタム関数を動的に生成できる | 乗算器ファクトリ multiply(n) |
| 両方行う | 受け取って変換・合成して返す | compose(f, g) などの関数合成 |
代表的な高階関数:map / filter / reduce
【配列: [1, 2, 3, 4, 5]】
map(x => x * 2) → [2, 4, 6, 8, 10] ← 全要素を変換
filter(x => x > 2) → [3, 4, 5] ← 条件に合うものだけ残す
reduce((a,b)=>a+b) → 15 ← 全要素を1つの値にまとめる
これら3つは「どう変換・抽出・集約するか」というロジックを外から渡すことで、繰り返し処理のパターンを共通化しています。
覚え方:「関数を食べる関数」
高階関数は「関数を食べる(受け取る)か、関数を産む(返す)か、その両方」と覚えましょう。「高階(こうかい)」の「高い階層」= 関数の上に立って関数を操る、とイメージするとわかりやすいです。
歴史と背景
- 1930年代 — 数学者アロンゾ・チャーチがラムダ計算(λ計算)を提唱。「関数を値として扱う」という数学的基盤が生まれる
- 1958年 — LISP(リスト処理言語)が誕生。関数を第一級オブジェクトとして扱う最初期のプログラミング言語となり、高階関数の実装が始まる
- 1970年代〜80年代 — ML・Haskellなど関数型言語が整備され、
map・filter・foldが標準的な道具として確立 - 2000年代 — JavaScriptの普及により、Webフロントエンドでコールバック関数・高階関数が爆発的に広まる
- 2010年代以降 — Python・Java(ラムダ式、Stream API)・C#(LINQ)・Swift・Kotlinなど主流言語が一斉に高階関数・ラムダ構文を取り込み、現代プログラミングの標準技法として定着
高階関数 vs 普通の関数 ─ どう違う?
実務でよく見る高階関数の使い方
// ❶ コールバック:処理が終わったら呼んでほしい関数を渡す
setTimeout(() => console.log("3秒後に実行"), 3000);
// ❷ map:全商品の価格に税率をかける
const prices = [100, 200, 300];
const taxed = prices.map(p => p * 1.1); // [110, 220, 330]
// ❸ filter:在庫ありの商品だけ絞り込む
const items = [{name:"A", stock:0}, {name:"B", stock:5}];
const inStock = items.filter(item => item.stock > 0);
// ❹ 関数を返す:消費税率をカスタマイズできる計算機を生成
function taxCalculator(rate) {
return (price) => price * (1 + rate);
}
const calc10 = taxCalculator(0.1);
console.log(calc10(1000)); // 1100
言語別サポート状況
| 言語 | 高階関数のサポート | 代表的な構文 |
|---|---|---|
| JavaScript / TypeScript | ◎ ネイティブ対応 | array.map(fn) / アロー関数 |
| Python | ◎ ネイティブ対応 | map(fn, list) / lambda |
| Java | ○ Java 8以降 | Stream API / Function<T,R> |
| C# | ○ ネイティブ対応 | LINQ / Func<T> デリゲート |
| Go | △ 関数は値だが簡易的 | 関数型を変数に代入 |
| Haskell | ◎ 言語設計の中核 | カリー化・部分適用が標準 |
関連用語
- 001-first-class-function.md — 関数を「値」として扱える性質。高階関数の前提条件
- 002-callback-function.md — 引数として渡される関数。高階関数の最も身近な使われ方
- 003-closure.md — 外側のスコープの変数を「閉じ込めた」関数。高階関数と組み合わせて使われる
- 004-lambda-expression.md — 名前を持たない無名関数。高階関数に渡す処理を簡潔に書く構文
- 005-functional-programming.md — 高階関数・不変データ・関数合成を中心とした設計パラダイム
- 006-map-filter-reduce.md — 配列操作の三大高階関数。実務で最もよく登場する
- 007-currying.md — 複数引数の関数を「一引数の関数を返す関数の連鎖」に変換するテクニック
- 008-pure-function.md — 同じ入力に常に同じ出力を返す副作用のない関数。高階関数と相性が良い