Lets say we have a bunch of functions like these:
def init(value):
return {'number': value}
def set_type(value):
if isinstance(value['number'], float):
value['type'] = 'float'
else:
value['type'] = 'integer'
return value
def set_is_positive(value):
if value['number'] < 0:
value['is_positive'] = False
else:
value['is_positive'] = True
return value
and compose function like this:
def compose(*funcs):
def compose_2_funcs(f1, f2):
return lambda arg: f1(f2(arg))
return reduce(compose_2_funcs, funcs)
The result of each function is passed as the argument of the next. For example composed = compose(f, g, h); result = composed(arg)
is the same as result = f(g(h(arg)))
. This allows us to have:
description_builder = compose(set_type, set_is_positive, init)
description_builder(5)
# Result: {'number': 5, 'type': 'integer', 'is_positive': True}
This is nice and flexible and I like to use it. But one thing bothers me. It's looks like a bit counter-intuitive that functions are specified in reversed order (especially for those, who don't know what is "function composition")
So I can define a function like this:
def compose_reversed(*funcs):
def composed(arg):
result = arg
for f in funcs:
result = f(result)
return result
return composed
It's even more readable(IMHO) and allows to specify functions in order they are called, so description_builder = compose_reversed(init, set_is_positive, set_type)
.
Finally, here are my questions :)
- Does this thing has a special name? Proposed in comments:
pipe
,compose_right
(along withcompose_left
). - What are pros and cons comparing to classic function composition?
p.s. I believe this question is applicable for any language with higher-order functions, not only python.