JavaScript

JavaScript でカリー化

More than 1 year has passed since last update.

カリー化と部分適用は違いがよくわからなかったので調べてみました。

Wikipedia によればカリー化とは・・・

複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。

引数の適用までは行わないそうです。

JavaScript で実装するとすると以下のような感じでしょうか。

Function.prototype.curry = function (context) {
  var func = this;
  var slice = Array.prototype.slice;
  return function partial() {
    var args = slice.call(arguments);
    if (args.length >= func.length) {
      return func.apply(context, args);
    } else {
      return function () {
        var argArray = slice.call(arguments);
        return partial.apply(context, args.concat(argArray));
      };
    }
  }
};

これでカリー化できます。

function sum(a, b, c) {
  console.log(a + b + c);
}

sum.curry()(1)(2)(3);
// 6

context 付きでも。

var greeter = {
  greeting: 'Hey,',
  greet: function (adj, noun) {
    console.log(this.greeting, adj, noun);
  }
};

greeter.greet.curry(greeter)('pretty')('girl');
// Hey, pretty girl

ただしこれだと部分適用時に、Function.prototype.bind を使ったときのように length が減っていかないのが残念です。

console.log(sum.length);
// 3
console.log(sum.bind(null, 1).length);
// 2

console.log(sum.curry().length);
// 0
console.log(sum.curry()(1).length);
// 0

何かうまい方法はないんでしょうか?