为何程序员都讨厌 reduce?

Anecdotally, Programmers Dislike "Reduce"

在日常代码审查中,我发现同事们对 map 和 filter 几乎从不提意见,但一旦代码里出现 reduce,总会收到“难以阅读”的反馈。虽然我个人偏爱 reduce,但在 JavaScript、Python 和 Swift 等语言中,它似乎确实不如其他函数优雅或直观。有趣的是,在我使用 Clojure 的那段时光里,这种抵触情绪几乎不存在。这究竟是 reduce 本身的问题,还是我们习惯了某种编程范式?我观察到的这个社交现象值得深思,或许代码审查的严格程度也在悄然变化。

简而言之:凭我的经验,人们喜欢 map 和 filter,但不喜欢 reduce。
  1. chubot

    关于性能更差这一点,我相当确定我当时就在现场,见证了 reduce 被“驱逐”出 Python 3 的过程——它从 Python 2 中的内置函数 reduce() 被降级到了 functools.reduce()。

    故事是这样的:2006 年或 2007 年某时,Guido van Rossum 正在调试一个性能问题,Google 内部代码审查工具(由他编写)中的某个网页渲染需要 30 多秒。

    这基本上算是一个“生产环境”事故,因为成千上万的 Google 工程师都依赖这个工具。这类请求可能占用了线程并耗尽了线程池。

    最终问题被追踪到一行用 reduce() 编写的文本换行算法。我不认为是他写的——可能是通过某个依赖引入的。正如大家所知,reduce() 本质上是这样工作的:

    s1 + s2

    s1 + s2 + s3

    s1 + s2 + s3 + s4

    ...

    当 s_i 是字符串时,这就是 O(n^2) 的复杂度。我记得如果你查看一个 5000 行以上的 diff,或者一个 5000 行以上的文件,问题就会显现。(像 Github 这样的较新程序也受此困扰)

    我相信,当时的 Python 中,+= 运算符已经经过优化以避免这个问题(就像几乎所有 JS 虚拟机一样)。或者你也可以使用“先 append() 到列表,最后 join()”的惯用写法。

    但 reduce() 基本上强制使用了这种低效的实现,我敢肯定这在 Python 3 中依然如此。

    ---

    所以基本上,Guido 花了很长时间调试一个与 reduce() 相关的性能问题,并决定将其剔除,以帮助用户避免这种“陷阱”。当时我是他的办公室同事,所以我记得这件事,但我不是 i […]

  2. snackbroken

    Map 和 Filter 之所以好用,是因为它们让你可以孤立地、局部地思考单个元素。而 Reduce(Fold)迫使你全局地思考中间结果。Reduce 还迫使你构想出相关类型的“零值”,这通常不难,但这确实构成了一些额外的脑力负担。

  3. japgolly

    我假设作者指的是 `fold`,即 `[A] -> B -> ((B,A) -> B) -> B`,而不是我通常认为的 reduce,即 `[A] -> ((A,A) -> A) -> A`。

    `fold` 非常棒且超级有用。它是将集合转换为单个值最简单、最便捷的方式。从个人经验来看,我和作者的观点截然相反。

同日更多故事

2026-09-16