"Alan G Isaac said:
Given a list of functions, it seems there must be a
Pythonic approach to composition. Something like
def compose(fns): return lambda x: reduce(lambda f,g: f(g),fns)(x)
This will not work because the argument 'x' is not "inside".
What is the proper formulation?
If you are only concerned with unary functions, then composition is
fairly trivial to deal with:
def compose(*fns):
def id(x): return x
def c2(f, g):
def h(x): return f(g(x))
return h
return reduce(c2, fns, id)
However, if you want to deal with functions that may take multiple
arguments, you must be a little more clever. Here's one way that seems
to work okay:
def compose(*fns):
def id(*args): return args
def box(res):
if isinstance(res, (list, tuple)):
return res
else:
return (res,)
def unbox(res):
if isinstance(res, (list, tuple)) and len(res) == 1:
return res[0]
else:
return res
def c2(f, g):
def h(*args):
return unbox(f(*box(g(*args))))
return h
return reduce(c2, fns, id)
For instance:
def f1(a, b):
return (a / b, a % b)
def f2(a, b):
return a + b
def f3(a):
return a + 2
h = compose(f3, f2, f1)
h(5, 3)
==> 5
This will work, but it's not the most efficient possible solution. You
could defer unboxing until the end by defining another intermediate
function.
Cheers,
-M