関数型プログラミング

関数型プログラミング

執筆済 ソフトウェア開発設計

計算を、値から値への変換として表す。

中心的な考え方#

概念 内容
純粋関数 同じ入力に同じ出力。副作用が無い
不変性 値を変更せず、新しい値を作る
第一級関数 関数を値として扱う
高階関数 関数を引数・戻り値にする
参照透過性 式をその値で置き換えられる

なぜ副作用を避けるのか#

純粋関数 f(x) は、x だけを見れば結果が分かる
   → 単体で理解できる
   → テストが書ける(準備が要らない)
   → 並行実行しても安全
   → キャッシュできる
   → 実行順序を入れ替えられる

局所的に理解できることが最大の価値。 副作用があると、その関数を理解するのに プログラム全体の状態を知る必要が出てくる。

実務での使い方#

純粋関数型言語(Haskell)を使わなくても、 方針として取り入れられる

swift
// 手続き的
var result: [Int] = []
for x in xs { if x > 0 { result.append(x * 2) } }

// 関数的
let result = xs.filter { $0 > 0 }.map { $0 * 2 }

mapfilterreduceベクトル化とも通じる 「ループを書かずに変換を宣言する」形。

副作用を端に追いやる#

副作用(I/O、DB、乱数、時刻)は無くせない。 中心を純粋に保ち、副作用を外側に集める設計にする。

[外側] 入力を読む
   ↓
[中心] 純粋な変換(テストしやすい)
   ↓
[外側] 結果を書く

これはクリーンアーキテクチャの 依存の向きとも一致する。

オブジェクト指向との関係#

対立しない。

  • OOP … 状態と振る舞いをまとめ、境界を作る
  • FP … 状態の変更そのものを減らす

Swift、Kotlin、Rust、TypeScript はいずれも 両方の要素を持つ。

参考文献#

ノート一覧を閉じる