無名関数とは
TL;DR : 無名関数は名前を付けずに即席で宣言できる関数。Python では lambda
、TypeScript / JavaScript ではアロー関数 =>
を使う。関数を変数のように扱う世界では、純粋関数・高階関数・コールバック関数と組み合わせることで威力を発揮する。
1. 無名関数の定義と文法
言語 | 代表構文 | 例 |
---|---|---|
Python | lambda 引数: 式 |
lambda x, y: x + y |
TypeScript | (引数) => 式 |
(x: number, y: number) => x + y |
無名関数は式として評価できるため、変数に代入したり、引数として渡したり、戻り値にしたりできる。
# Python
square = lambda x: x ** 2
print(square(4)) # 16
// TypeScript
const square = (x: number): number => x ** 2;
console.log(square(4)); // 16
関数定義 (def
/function
) との違い
-
スコープ: 無名関数もクロージャを形成できるが、Python の
lambda
は 1 式しか書けず、複数文は不可。 - デバッグ: 名前がないため、スタックトレースで識別しづらい。
2. 純粋関数 (Pure Function) との関係
無名関数 = 純粋関数 ではないが、無名関数は純粋関数として書かれることが多い。純粋関数の条件は ①副作用なし ②同じ入力→同じ出力。
# 副作用なしの lambda
increment = lambda x: x + 1
// 副作用があるアロー関数 (純粋ではない)
let total = 0;
const impure = (x: number) => total += x; // グローバル変数を書き換え
3. 高階関数とコールバック関数
- 高階関数: 関数を引数に取る or 戻り値に返す関数。
- コールバック関数: 高階関数に渡され、「後で呼び戻される」関数。多くの場合、無名関数が用いられる。
# map は高階関数; 第1引数はコールバック
nums = [1, 2, 3]
doubles = list(map(lambda n: n*2, nums))
// setTimeout は高階関数。1番目の引数に無名コールバックを渡す
setTimeout(() => console.log("done"), 1000);
4. 典型ユースケース
4.1 データ変換・フィルタリング
filtered = list(filter(lambda x: x % 2 == 0, range(10))) # [0,2,4,6,8]
const filtered = [ ...Array(10).keys() ].filter(n => n % 2 === 0);
4.2 ソートキー
students = [("Akira", 24), ("Ben", 19)]
print(sorted(students, key=lambda s: s[1])) # 年齢順
const students: [string, number][] = [["Akira",24], ["Ben",19]];
console.log(students.sort((a,b) => a[1]-b[1]));
4.3 イベントハンドリング / 非同期
import fs from "fs";
fs.readFile("data.txt", "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});
5. パフォーマンスと実装上の注意
-
オーバーヘッドは僅少: 呼び出しコストは名前付き関数と同等。ただし、ループ内で毎回
lambda
を生成するとガベージコレクション負荷が増える。 - 再利用性: 同じ処理を複数回使うなら名前付き関数に切り出すべき。
-
デバッグ難度: スタックトレースに
<lambda>
やanonymous
と表示される。 - 可読性: 複数文や複雑なロジックを無名関数に詰め込むと可読性が急落。
-
再帰不可 (Python):
lambda
は自身を参照しにくく、再帰より名前付き関数を推奨。
6. ベストプラクティス
シナリオ | 無名関数を使う? | 理由 |
---|---|---|
1 回限りの短い処理 | ✅ | 定義場所を探すコストを削減 |
複数回再利用 | ❌ | DRY 原則に従い関数名を付ける |
複雑な処理 | ❌ | 可読性・テスト容易性優先 |
イベントコールバック | ✅ | コードの局所性が高まる |
パフォーマンスクリティカルかつループ生成 | ❌ | 生成コストを抑える |
7. まとめ
無名関数は「関数も第一級オブジェクト」という思想を具体化する最小単位。短く、一時的で、純粋な処理を書くときに最適で、高階関数やコールバックの相棒として不可欠だ。ただし、再利用性・可読性・デバッグ性を犠牲にしないよう、適材適所で使い分けよう。
合言葉 : “大は小を兼ねない” —— 短い処理は無名関数、長い処理は名前付き関数!