Search code examples
pythonfunctional-programmingcomposition

Reversed function composition in python(not only)


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 :)

  1. Does this thing has a special name? Proposed in comments: pipe, compose_right (along with compose_left).
  2. 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.


Solution

  • So, it seems that we don't have more opinions on this.

    Just to summarize:

    1. proposed names are pipe and compose_right (along with compose_left)
    2. Not to much here. It's looks like matter of personal tastes and particular case. 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.