# Is this a good use for lambda

Terry Reedy tjreedy at udel.edu
Thu Dec 23 01:15:09 CET 2004

```"Nick Coghlan" <ncoghlan at iinet.net.au> wrote in message
news:41C97407.7090301 at iinet.net.au...
> Although if you genuinely prefer a functional programming style,
> I'd go with  Terry's answer rather than mine.

The 'iterative' version can also be written recursively, which to most is
functional.  For me, the important question for general composition is
whether one unpacks the sequence of functions to construct a nested
sequence of wrappers (via compose2) *before* one has any data to apply it
to, or whether one bundles the flat list of functions, as it is, with a
generic composer which, once it gets a piece of data to operate on, unpacks
and applies the functions one at a time.  The former has a certain
theoretical elegance, the latter seems more practical and, for Python,
probably faster.  So my previous answer was about how the make the former
approach perhaps clearer, by explicit naming compose2, but not a claim that
it is necessarily the 'better' approach.

> (Incidentally, I didn't even know what the reduce trap *was* until Terry
> described it, but the iterative version avoids it automatically)

Yes, I noticed that   A properly-written recursive version of the unpack
and apply algorithm would do the same.

To me, Python's builtin reduce has two related problems.  The second is
that it overlays two related but distinct functions, one with three
parameters and the other, a special case, with just two.  The first problem
is that as one way to do the second, it defines the three parameter

To explain the first:  the three-param signature of Python's reduce is
reduce(update_result_with_item, items, initial_result)
The order of result and item(s) is switched between the update function and
reduce itself.  Some people (including GvR according to a post on PyDev)
find this confusing and error-prone enough that they avoid using reduce.

The proper, order-consistent signature is either
reduce(update_result_with_item, initial_result, items)
or possibly (but I prefer the above)
reduce(apply_item_toupdate_result, items, initial_result)
so that the order of the args to the update function matchwa the order they
are given to reduce.

As to the second problem: if the abbreviated and slightly specialized
reduce1(updater, items), equivalent to
def reduce1(updater, items):
if items: return reduce(updater, items[0], items[1:])
else raise TypeError("reduce1 requires at least 1 item")
is important enough to be in builtins, then perhaps it was/is important
enough to have its own name instead of being overlayed on reduce with a
perverted signature.  (Though, reduce1(applier, items) *could* be overlayed
on full reduce with the second consistent signature).

Terry J. Reedy

```