inject、畳み込み2006年10月16日 22時06分

IT戦記 - Perl で再帰呼出し時のスタック間データ共有を読んだ時点では気づきもせず、Kazuho@Cybozu Labs: JavaScript で Generic Programming にいたってようやく思い当たったのだが、Ruby の Enumerable#injectPython の reduce というのはこういうときに使うものなのかもしれない。

// requires Prototype.js
function count_tags(node) {
  return $A(node.childNodes).inject({}, function (tag, kid) {
    if (kid.nodeType != 1) return tag;
    tag[kid.nodeName] = (tag[kid.nodeName] || 0) + 1;
    return $A(kid.childNodes).inject(tag, arguments.callee);
  });
}

さて、このような畳み込み関数の名前は inject、reduce、foldl など言語によりばらばらで、逆に言えばこれぞというべき名前がないようで、Ruby のフォーラムでも inject というメソッド名はわかりづらいというトピックがあった。代替案として出ていたのは combine、each_with_state、accumulate など。個人的には、reduce は何を「減らす」のよくわからず、foldl は JavaScript の命名習慣から外れているようで、「リストの要素間に二項演算を『注入』する」という解釈も含めて inject が好みなのだが、もし JavaScript に採用されることがあっても名前は reduce になるんだろうなという気がする。

ところで、畳み込み関数について検索していたら、foldl.com というサイトを見つけた。JavaScript を有効にする必要があるがなかなか面白いサイトだ。ここで、ふと思いついて foldr.com とアドレスバーに入力してみたら……。いやはや、盛大に笑わせてもらった。