31 points praptak 2 days ago 35 comments
eimrine 2 days ago | parent
theamk 2 days ago | parent
If you are multiplying, you are likely doing heavy math, and you'll be using numpy - which does not need reduce either.
If you are going to return a list of dict, then it's much faster to mutate the results, so using "reduce" will have significant performance implications (unless you want to return input argument, mis-using it as a glorified "for" loop)
And if returning not a list/dict, if you can use "min" or "max" or "any" or "all" or "next" (take the first element), then you should use it - it will be easier to read and faster too.
So what does this leave us for "reduce"? Frankly, not much. I've only seen it in merging immutable status codes, and that was pretty niche usecase to begin with.
(this was all for Python. In other languages without nice list of built-ins reduce might make more sense)
rsfern 1 day ago | parent
Pinus 1 day ago | parent
theamk 15 hours ago | parent
Python 3.13.5 (main, Jul 15 2026, 20:25:40) [GCC 14.2.0] on linux
>>> x = [[n]*1000 for n in range(1000)]; import timeit, itertools, functools, operator
>>> timeit.timeit("len(list(sum(x, [])))", number=10, globals=globals())
13.009033881127834
>>> timeit.timeit("len(list(list(functools.reduce(operator.add, x, []))))", number=10, globals=globals())
12.941937348805368
>>> timeit.timeit("len(list(itertools.chain.from_iterable(x)))", number=10, globals=globals())
0.0706032607704401
>>> timeit.timeit("out=[]; [out.extend(i) for i in x]; len(out)", number=10, globals=globals())
0.06334403157234192
>>> timeit.timeit("len([i for a in x for i in a])", number=10, globals=globals())
0.1232151910662651
mutable is fastest, itertools is just a bit slower, list comprehension is 2x slower, both "sum(..., [])" and "reduce" are 200 times slower!evnix 1 day ago | parent
I come across reduce once in a few months, then I think it's a neat trick and a nice to have function.
then I forget it's even available and don't ever use unless these days LLM brings it up again.
karmakaze 1 day ago | parent
billyp-rva 1 day ago | parent
slopnt 1 day ago | parent
g8oz 1 day ago | parent
japgolly 1 day ago | parent
`fold` is awesome and super useful. It's the easiest and most convenient way to turn a collection into a single value. Put me anecdotally in the opposite bucket.
wannabe44 47 minutes ago | parent
You will eventually learn about something called "for loop", and it will be nice.
t-3 43 minutes ago | parent
mrkeen 34 minutes ago | parent
Plus it forces you out of whatever lazy/streaming paradigm you had going on. If your foldr produces a list, downstream can start consuming it in constant memory as long as you let it do its thing.
8note 27 minutes ago | parent
nightpool 6 minutes ago | parent
Associativity also makes fold hard. It's not super trivial to know when you might need e.g. left fold vs right fold
s-zeng 1 day ago | parent
In languages like python or Java though, you don't really have access to many of the higher power functional traversals however. So that puts you into a similar kind of bind as working in a language with only while loops
snackbroken 1 day ago | parent
mrkeen 40 minutes ago | parent
snackbroken 14 minutes ago | parent
chubot 38 minutes ago | parent
The story is that sometime in 2006 or 2007, Guido van Rossum was debugging why a web page in Google's internal code review tool (which he wrote) was taking 30+ seconds to render.
This is basically a "production" incident, since thousands of Google engineers relied on the tool. Requests like this were probably tying up threads and exhausting thread pools, perhaps
Eventually it was tracked down to a line wrapping algorithm written with reduce(). I don't think he wrote it -- it may have come in through a dependency. As many know, reduce() is basically:
s1 + s2
s1 + s2 + s3
s1 + s2 + s3 + s4
...
And that's O(n^2) when s_i are strings. And I think it showed up if you viewed a 5000+ line diff, or a 5000+ line file. (Newer programs like Github also suffer here)I believe, in Python at that time, += was already optimized to avoid this (just like essentially all JS VMs are). Or you can use the idiom of append() to list and join() after.
But reduce() basically forces the inefficient implementation, and I'm sure this is still true in Python 3.
---
So basically Guido spent a long time debugging a performance problem related to reduce(), and made the decision to eject it, to help users avoid "footguns". I was his officemate at the time, so I recall this, but I wasn't involved directly
Also, somebody contributed reduce() to Python way back in the 90's, as well as other functional idioms. He wouldn't have added that himself -- it was never his preferred style.
He preferred a more imperative style. But he allowed those contributions, and then slightly regretted it later.
https://docs.python.org/3/library/functools.html#functools.r...
taeric 26 minutes ago | parent
That is, why couldn't they have done the essentially same trick that you reference for += with reduce?
kelipso 19 minutes ago | parent
justonceokay 16 minutes ago | parent
bmandale 15 minutes ago | parent
There is an optimization for lists, and maybe that's what GP is remembering. l += is functionally different from l = l +. The former mutates l, whereas the latter creates a new l. The difference matters when the line above is m = l. The mutation version will mutate m as well (they're the same reference), the creates new version will not. This optimization can just as easily turn into a footgun if the programmer is unaware of it, and in that sense is unpythonic.
bjourne 8 minutes ago | parent
semiinfinitely 36 minutes ago | parent
ChrisMarshallNY 30 minutes ago | parent
I find the two ways that you call it to be a bit annoying (not a showstopper). It just seems a bit "kludgy" to me.
sumolessons 26 minutes ago | parent
Might be nonsensical, but one thing I sometimes wonder is why I reach for reducing a list to a value more often than I need to generate a list from a starting value. I guess the asymmetry has something to do with the kinds of applications I work on.
norir 24 minutes ago | parent
juancn 23 minutes ago | parent
The FUBAR potential with map and filter is much smaller, with reduce it depends on deep knowledge of the internals of the reduction itself.
yakshaving_jgt 21 minutes ago | parent
WesolyKubeczek 19 minutes ago | parent
Glyptodon 14 minutes ago | parent
franey 14 minutes ago | parent
array.reduce(
(accumulator, currentItem) => {...},
initialValue,
)
In .filter(), The current item is the 1st argument and the intermediate/accumulated value comes later: filter((currentItem, index, intermediateArray)) => ...)I use .filter() more often, so that argument ordering where currentItem is right next to the array is more intuitive for me