2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるカリー化と関数合成:関数設計の抽象化と再利用性の強化

Posted at

概要

関数は「処理をまとめたもの」では終わらない。
それは**“データ変換の流れを抽象化し、制御構造を分割可能にする設計単位”**である。

JavaScriptは、関数を第一級オブジェクトとして扱う言語であり、
その特性を最大限に活かすことでカリー化・関数合成による設計のモジュール化・柔軟化が可能になる。

本稿では、カリー化と関数合成の基本、設計上の価値、実用的な構造戦略を提示する。


1. カリー化(Currying)とは

function add(a) {
  return function (b) {
    return a + b;
  };
}

const add5 = add(5);
console.log(add5(3)); // → 8
  • ✅ 複数引数の関数を一引数ずつ分割して再適用できる関数に変換
  • 一部の引数を先に固定できる(部分適用)

2. 汎用的なカリー化関数の定義

function curry(fn) {
  return function curried(...args) {
    return args.length >= fn.length
      ? fn.apply(this, args)
      : (...next) => curried(...args, ...next);
  };
}

function multiply(a, b, c) {
  return a * b * c;
}

const curriedMultiply = curry(multiply);
console.log(curriedMultiply(2)(3)(4)); // → 24
  • ✅ 関数の引数を段階的に提供可能な形に変換
  • ✅ パイプライン構造やDI的な使い方にも応用可

3. 関数合成(Composition)とは

const compose = (f, g) => (x) => f(g(x));

const double = x => x * 2;
const square = x => x * x;

const doubleThenSquare = compose(square, double);

console.log(doubleThenSquare(3)); // → 36
  • f(g(x)) のように関数を外側から順に適用
  • ✅ 入力 → 加工 → 出力 の直列化された処理設計に有効

4. 関数パイプラインの構造化(pipe)

const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

const process = pipe(
  x => x + 1,
  x => x * 2,
  x => `Result: ${x}`
);

console.log(process(3)); // → "Result: 8"
  • ✅ 左から右へ読みやすい順序で適用
  • データフローの明確化・ステップごとの分離に優れる

5. カリー化 × 合成による抽象的ビジネスロジックの設計例

const filterBy = curry((key, value, arr) =>
  arr.filter(obj => obj[key] === value)
);

const users = [
  { id: 1, role: 'admin' },
  { id: 2, role: 'user' },
  { id: 3, role: 'admin' }
];

const filterAdmins = filterBy('role')('admin');
console.log(filterAdmins(users)); // → [{id:1, ...}, {id:3, ...}]
  • ✅ フィルター条件を部分適用して再利用可能に
  • 構造を関数に分解し、再構成できる設計に昇華

設計判断フロー

① 再利用性のある処理は、部分適用できるように構造化されているか?

② 関数を組み合わせるとき、合成によって処理の流れを明確化できるか?

③ 入力 → 加工 → 出力の構造をパイプラインとしてモデル化できているか?

④ 固定引数を渡すために、使い回し可能な中間関数に分解できているか?

⑤ ロジックの直列化によって副作用を制御できているか?

よくあるミスと対策

❌ 関数を定義したが、使い回しや再構成が困難

→ ✅ カリー化して引数を固定しやすくする


❌ ロジックが長くなり、読みづらい処理列に

→ ✅ 関数合成や pipe を使ってデータ変換の流れを明示化


❌ 引数の受け渡しが複雑でスパゲッティ構造に

→ ✅ 小さな関数に分解して合成 / 部分適用で構成可能にする


結語

カリー化と関数合成とは、
単なる構文のトリックではない。
それは**“ロジックを分解し、組み立て直し、制御可能な単位として再構成するための抽象化戦略”**である。

  • 関数は「処理」ではなく「変換構造」として設計する
  • カリー化は再利用性、合成は構造の明快化を担う
  • 複雑なロジックは、関数として分割・再構成することで安全に制御可能

JavaScriptにおける関数抽象化とは、
“再利用可能な構造単位としてロジックを設計するアーキテクチャ戦略”である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?