JavaScriptでカリー化してみた

オブジェクト指向なのに、関数型チックな使い方もできると評判のJavaScriptですが、せっかくなのでカリー化をやってみました。


カリー化とは、「引数を幾つか固定すると、残った引数の関数が得られる」こと(Wikipediaより抜粋)です。
続きはwebで!


curry関数を定義して関数をカリー化している例はよく見かけるのですが、Functionオブジェクトのメソッドで実現している例はありませんでした。
ということでcurryメソッドをつくってみました。

Function.prototype.curry = function() {
    var length = this.length;
    if (length < 2) {
        return this;
    }
    var args = [];
    var methods = [];
    var _method = this;

    methods.push(function(a) {
        args.push(a);
        return  _method.apply(this, args);
    });

    for (var i = 0; i < length - 1; i++) {
        methods.push(function(a) {
            args.push(a);
            return methods.pop();
        });
    }
    return methods.pop();
}


使い方はこんな感じです。

var fn = function(a, b, c) {
    return 3 * a + b + 2 * c;
}
// カリー化する
var curriedFn = fn.curry();
// 引数を与えていく
curriedFn(1)(2)(4); // 13


ポイントは、引数と関数を保持しておく配列に対してインデックスを指定せずに要素の追加・取出しを行っている点です。
変数iを基準にしてインデックスで配列操作をしようとすると、関数定義の中でiを参照している箇所で最終的なiの値しか取得できません。
引数の数が3個だったら常に(i = 3)となります。


これは関数の中から外側の変数を参照する際に、関数実行時の変数の値をたどるためです。


実際に使う機会があるかはわかりませんが、Functionオブジェクトのメソッドとしてのカリー化の実装例として。