# [Python-Dev] functools.compose to chain functions together

Steven D'Aprano steve at pearwood.info
Mon Aug 17 09:43:52 CEST 2009

```On Mon, 17 Aug 2009 08:10:16 am Martin v. Löwis wrote:

> I don't think he did. Comparing it to the one obvious solution (use
> a lambda expression), his only reasoning was "it is much easier to
> read". I truly cannot believe that a compose function would be
> easier to read to the average Python programmer: if you have
>
>   def foo(data):
>     return compose(a, b(data), c)
>
> what would you expect that to mean?

foo is a factory function that, given an argument `data`, generates a
function b(data), then composes it with two other functions a and c,
and returns the result, also a function.

> Please rewrite it as a regular
> Python expression, preferably without looking at the patch that
> has been proposed first. I bet there is a 50% chance that you get
> it wrong (because there are two possible interpretations).

But surely only one of them will agree with the standard definition of
function composition. Both Mathworld and Wikipedia agree that f∘g(x)
is equivalent to f(g(x)):

http://mathworld.wolfram.com/Composition.html
http://en.wikipedia.org/wiki/Function_composition

and I don't see any reason why a compose() function shouldn't do the
same.

(Aside: how do I look at the patch? The only link I have is here:
http://mail.python.org/pipermail/patches/2007-February/021687.html
but I can't see how to get to the patch from there.)

foo could be written as:

def foo(data):
return lambda *args, **kwargs: a(b(data)(c(*args, **kwargs)))

Or without lambda:

def foo(data):
def composed(*args, **kwargs):
return a(b(data)(c(*args, **kwargs)))
return composed

This soon gets unwieldy:

def foo(arg1, arg2, arg3):
return compose(
f, g, h, factory(arg1), factory(arg2), factory(arg3)
)

versus

def foo(arg1, arg2, arg3):
return lambda *a, **kw: (
f(g(h(factory(arg1)(factory(arg2)(factory(arg3)(*a, **kw))))))
)

but presumably composing six functions is rare.

A further advantage of compose() is that one could, if desired,
generate a sensible name and doc string for the returned function.
Depends on how heavyweight you want compose() to become.

I think the compose() version is far more readable and understandable,
but another factor is the performance cost of the generated function

For the record, Haskell makes compose a built-in operator:

It doesn't appear to be standard in Ruby, but it seems to be commonly
requested, and a version is on Facets:

http://facets.rubyforge.org/apidoc/api/core/classes/Proc.html#M000161

--
Steven D'Aprano
```