"Nick Coghlan" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > 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 function with contradictory parameter orders. 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 -- http://mail.python.org/mailman/listinfo/python-list