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 :)
pipe
, compose_right
(along with compose_left
).p.s. I believe this question is applicable for any language with higher-order functions, not only python.
So, it seems that we don't have more opinions on this.
Just to summarize:
pipe
and compose_right
(along with compose_left
)compose_left
is more like function composition in mathematics, while compose_right
may be considered more readable since functions are listed in the same order as applied.Marking this as answer, until somebody wants to make more detailed.