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" [1] 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)



Nick Coghlan   |   |   Brisbane, Australia