inject、畳み込み ― 2006年10月16日 22時06分
IT戦記 - Perl で再帰呼出し時のスタック間データ共有を読んだ時点では気づきもせず、Kazuho@Cybozu Labs: JavaScript で Generic Programming にいたってようやく思い当たったのだが、Ruby の Enumerable#inject や Python の 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 とアドレスバーに入力してみたら……。いやはや、盛大に笑わせてもらった。
コメント
_ mal ― 2006年12月07日 22時24分
_ nanto_vi ― 2006年12月08日 01時13分
"Python's moribund reduce"という表現が気にかかります。reduceが実際には使われていないということでしょうか?
個人的には初期値の指定はぜひほしいところです。
_ mal ― 2007年04月10日 23時22分
http://bonsai.mozilla.org/cvslog.cgi?file=mozilla/js/src/jsarray.c&rev=HEAD&mark=3.105
こんなコメントじゃわからないよー!
[3,4,5].reduce(function(a,b){return a + b}, 6) // 18
[3,4,5].reduceRight(function(a,b){return a - b}, 20) // 8
動いてます。
※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。
※投稿には管理者が設定した質問に答える必要があります。
トラックバック
このエントリのトラックバックURL: http://nanto.asablo.jp/blog/2006/10/16/563410/tb
https://bugzilla.mozilla.org/show_bug.cgi?id=363040
やっぱ reduce (-_-)
確か inject は SmallTalk 由来、reduce は Common Lisp あたりでしょうか。