高階関数で書き直し

昨日の JavaScript で Listモナド [id:gakuzo:20090401:1238599220] ですが、サンプルのために expandCharClass と expandAltWords をベタっと書きましたが、本来ならもう少しすっきり書きたいですね。

先に String.prototype.toArray を定義しておきます。prototype.js を使用している場合は必要ありません。

// prototype.js では実装されているので prototype.js を使用している場合は必要ありません。
if (!String.prototype.toArray) {
    String.prototype.toArray = function() {
        var result = [];
        for (var i = 0, n = this.length; i < n; i++) {
            result[i] = this.charAt(i);  // Array.prototype.push を使用しないのは MacIE 対策
        }
        return result;
    }
}

そうすると expandCharClass や expandAltWords は次の様に書けます。

function expandCharClass(str) {
    return expandCommon(str, /(.*)\[(.*?)\](.*)/, String.prototype.toArray, [], arguments.callee);
}
function expandAltWords(str) {
    return expandCommon(str, /(.*)\{(.*?)\}(.*)/, String.prototype.split, [","], arguments.callee);
}
function expandCommon(str, regexp, matchedHandler, handlerArguments, ref) {
    if (!str.match(regexp)) return [str];
    var matched = matchedHandler.apply(RegExp.$2, handlerArguments);
    return jQuery.map(matched, function(e) {return RegExp.$1 + e + RegExp.$3;}).bind(ref);  // jQuery版
    // return matched.map(function(e) {return RegExp.$1 + e + RegExp.$3;}).bind(ref);       // prototype.js版
}

高階関数さまさまですね。

因みに昨日の記事で再帰してたり、今回 bind 使ったりしているのは、"img[012][abc].png" の様に複数回パターンが存在した時の為です。

2009-04-02 21:41 編集

jQueryprototype.js があること前提だったので map 使って expandCommon を簡略化。

2009-04-04 11:23 編集

map 使って書き直したので、Array.prototype.push が 1度しか使われなくなり、このエントリの本題とも関係ないので Array.prototype.push の実装を削除。