【かんすうがたぷろぐらみんぐ】

関数型プログラミング とは?

最終更新:
💡 データの変換を関数で組み合わせ、副作用を分ける

入力から出力への変換を関数で組み合わせ、副作用や共有データの変更を抑えるプログラミングの考え方。純粋関数、不変データ、mapなどの使い方、constやObject.freezeの限界を解説します。

📌 このページのポイント
関数型:変換を組み合わせる元の配列12345map2倍にする246810filter4より大きい6810reduce合計する24reduceの初期値は0この例では元の配列を変更しない渡す関数の副作用は、別に確認するconstは配列の中身まで固定しない
値の列をmap、filter、reduceで変換・集約する例です。mapなどを使うだけで純粋になるわけではありません。新しい値を作ることとconstによる再代入の禁止も区別します。
ひよこ ひよこ
関数型は、関数を書けばよいの?
ペンギン先生 ペンギン先生
関数を使うだけではなく、入力から出力への変換を組み合わせ、副作用や共有データの変更を抑える考え方だよ。Haskellなどの言語だけでなく、PythonやJavaScriptでも、そのスタイルを取り入れられる。
ひよこ ひよこ
純粋関数とは?
ペンギン先生 ペンギン先生
同じ入力なら同じ出力を返し、外側の状態を変更したり画面へ出力したりしない関数だよ。たとえば数値を2倍して返す処理なら、入力3に対して6を返す。時刻や乱数を内部で読み、結果が変わる場合は純粋とはいえないね。
ひよこ ひよこ
データを変えないと、更新できなくない?
ペンギン先生 ペンギン先生
元のデータを直接書き換える代わりに、新しい値を返す方法があるよ。配列ならmapで各要素を変換したり、filterで必要なものを選んだりできる。ただし渡す関数が外部のデータを変えれば副作用があるので、メソッド名だけでは純粋さを判断しないんだ。
ひよこ ひよこ
JavaScriptのconstなら中身も不変?
ペンギン先生 ペンギン先生
constが禁止するのは変数への再代入だよ。constで宣言した配列にpushすることなどはできる。Object.freezeも、そのオブジェクトの直下のプロパティを固定するもので、入れ子のオブジェクトまで自動で固定するわけではないんだ。
ひよこ ひよこ
副作用は全部なくすべき?
ペンギン先生 ペンギン先生
画面の更新やファイルの保存など、必要な副作用もあるよ。計算部分と、外部へ作用する部分を分けると、入力と出力で計算を検証しやすい。Reactも描画は純粋に保ち、副作用はイベント処理などで扱う。関数型を使えば競合や不具合が絶対に起きない、とは考えないようにしよう。
もっと詳しく知りたい人へ

オブジェクト指向とは両立できない?

両方の考え方を組み合わせられます。Pythonの公式資料も、オブジェクトを引数や返り値にする関数の使い方を説明しています。オブジェクト指向は必ず共有状態を書き換える、関数型はオブジェクトを使えない、という二択にはしません。

関数の中でローカルな値を変えたら、必ず不純?

呼び出しの中で新しく作った値の変更が外側から見えず、入力と出力の関係も一定なら、内部の変更だけで直ちに不純とは限りません。Reactの公式資料もこの局所的な変更を区別しています。入力として受け取ったオブジェクトや共有の値を変えることとは分けます。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「関数型プログラミング」って出てきたら「データの変換を関数で組み合わせる考え方」と思えばだいたいOK!
📖 おまけ:英語の意味
「Functional Programming」 = 関数を中心に組み立てるプログラミング
💬 数学の関数のように、入力から出力を得る考え方を重視します。関数を使うだけ、あるいは関数に分割するだけで、すべてが純粋になるわけではありません。

参考資料

← 用語集にもどる