プログラマーはなぜ「reduce」を嫌うのか
Anecdotally, Programmers Dislike "Reduce"
mapやfilterはコードレビューでほとんど文句を言われないのに、reduceを使うと「読みにくい」と指摘されることが多い。著者はこの経験から、プログラマーがreduceを好まない傾向があると感じ、その理由として可読性の低さ、馴染みの薄さ、パフォーマンス、言語によるエレガンスの違いなどの仮説を挙げる。Clojureではこのフィードバックはなかったという。
私の経験では、人はmapとfilterは好むが、reduceは好まない。
HNでの議論
19- chubot
パフォーマンスが悪化するという点に関連して、Python 3でreduceが「追放」されたとき、私はその場にいたとほぼ確信している。つまり、Python 2の組み込みreduce()ではなく、functools.reduce()に格下げされたのだ。
話は2006年か2007年ごろ、Guido van RossumがGoogleの社内コードレビューツール(彼が書いた)で、あるWebページのレンダリングに30秒以上かかる理由をデバッグしていたときに遡る。
これは基本的に「本番」インシデントで、何千人ものGoogleのエンジニアがそのツールに依存していた。このようなリクエストがスレッドを占有し、スレッドプールを枯渇させていた可能性が高い。
最終的に、reduce()で書かれた行折り返しアルゴリズムに行き着いた。彼が書いたものではないと思う——依存関係を通じて入ってきたのかもしれない。多くの人が知っているように、reduce()は基本的にこうだ:
s1 + s2
s1 + s2 + s3
s1 + s2 + s3 + s4
...
そしてs_iが文字列の場合、これはO(n^2)になる。5000行以上のdiffや5000行以上のファイルを表示したときに発生したと思う。(Githubのような新しいプログラムもここで苦しんでいる)
当時のPythonでは、+=はすでにこれを避けるように最適化されていたはずだ(基本的にすべてのJS VMがそうであるように)。あるいは、リストにappend()してからjoin()するイディオムを使うこともできる。
しかしreduce()は基本的に非効率な実装を強制する。そしてこれがPython 3でも依然として真実であることは間違いない。
---
つまり、Guidoはreduce()に関連するパフォーマンス問題のデバッグに長い時間を費やし、ユーザーが「フットガン」を避けられるように、それを排除する決定を下したのだ。当時私は彼と同じオフィスにいたのでこれを覚えているが、私はその場にいなかった […]
- snackbroken
MapとFilterは、単一の要素を孤立してローカルに推論できるので良い。Reduce(Fold)は、中間結果についてグローバルに推論することを強制する。またReduceは、関連する型の「ゼロ」値を思い描くことを強制する。これは通常それほど難しくはないが、余分な精神的オーバーヘッドになる。
- japgolly
著者は`fold`、つまり`[A] -> B -> ((B,A) -> B) -> B`について話しているのであって、私がよくreduceと考える`[A] -> ((A,A) -> A) -> A`ではないと仮定する。
`fold`は素晴らしく、超便利だ。コレクションを単一の値に変換する最も簡単で便利な方法だ。私を逸話的に反対のバケツに入れてくれ。