コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

JavaScriptの二重のアロー演算子を使ったカリー化がわかりにくいので分解して理解する

読んでいてたまにわからなくなるタイミングがあるので記憶を呼び起こすためのメモ

カリー化とは

Wikipedia曰く以下のようなことをカリー化としている。

カリー化 (currying, カリー化された=curried) とは、複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。 - カリー化 - Wikipedia

実際にカリー化でやりたいことは「引数が複数ある関数において、個々の引数を固定した関数をつくる」ということである。

// ベースの値を足す値と引く値をセットするメソッド
let normalFunction = (baseNumber, addNumber, subtractNumber) => {
  console.log(baseNumber + addNumber - subtractNumber);
};

// ベースの値を固定して、他の値は引数としてとるfunctionを作る(これはカリー化とは言わず部分適用と呼ばれる)
let fixBaseFunction = (baseNumber) => {
  return (inAddNumber, inSubtractNumber) => normalFunction(baseNumber , inAddNumber , inSubtractNumber);
};

let base100Function = fixBaseFunction(100)

// 以下は同じ意味
normalFunction(100,20,30);
fixBaseFunction(100)(20,30);
base100Function(20,30);


// 似た形ですべての引数を単独の引数の形に変形する、これがカリー化
let curriedFunction = (inBaseNumber) => {
  return (inAddNumber) => {
    return (inSubtractNumber) => {
      normalFunction(inBaseNumber , inAddNumber , inSubtractNumber);
    };
  };
};

// 他のfunctionと同じ結果となる
curriedFunction(100)(20)(30);

このようにカリー化を行うと「baseNumberだけ100で大体固定なんだけどな…」のようなシーンに100で固定した関数を作り出して渡すということが可能になる。

なお、カリー化は引数を1つずつ分割することを意味し、部分的に引数を分割すること(上記の例で言う fixBaseFunction )は「部分適用」と呼ばれる。

アロー演算子を二重に使ってカリー化をする

カリー化をとても雑にいうと「引数を複数持つ関数を引数を一つずつ取る形に分割する」ということなので、それをアロー演算子を重ねて使うとかんたんに実現できる

let originalFunction = (x, y) => {
  return x - y;
};


let curriedFunction = (x) => {
  return (y) => {
    return x - y;
  };
};

let arrowCurriedFunction = (x) => (y) => {
  return x - y;
};

let minimumArrowCurriedFunction = x => y => x - y;

参考サイト