On 12 July 2013 07:01, Nick Coghlan firstname.lastname@example.org wrote:
The strange contortions of the "fast sum for lists" discussions got me wondering about whether it was possible to rehabilitate reduce with a less error-prone API. It was banished to functools in 3.0 because it was so frequently used incorrectly, but now its disfavour seems to be causing people to propose ridiculous things.
The 2.x reduce is modelled on map and filter: it accepts the combinator as the first argument, and then the iterable, and finally an optional initial value. The most common error was failing to handle the empty iterable case sensibly by leaving out the initial value, so you got a TypeError instead of returning a result.
So, what if we instead added a new alternative API based on Haskell's "fold"  where the initial value is mandatory:
def fold(op, start, iterable): ...
Efficiently merging a collection of iterables into a list would then just be:
data = fold(operator.iadd, , iterables)
I'd personally be in favour of the notion of also allowing strings as the first argument, so you could instead write:
data = fold("+=", , iterables)
This could also be introduced as an alternative API in functools.
(Independent of this idea, it would actually be nice if the operator module had a dictionary mapping from op symbols to names, like operator.by_symbol["+="] giving operator.iadd)
This sounds like a good idea to me (although by_symbol could well have a more catchy name) -- there are so many places where "lambda a, b: a
...But then I start suggesting extensions like having operator.* auto curry: "operator.iadd(left=foo)(bar)" === "operator.iadd(foo, bar)" (currying should require separate keyword-only syntax, and those keywords always make a curried function). And uncurry -- we need that if we want this to work with map.