# Combinators in Python

Posted by Josh Bohde

Inspired by the Coffeescript library Katy, I've been exploring using combinators with Python. The result can be found in my Functional Python repository.

In my previous post on Function Python, I was attempting to translate the following imperative code into different styles.

`def imperative_style(xs):    results = []    for x in xs:        if x >= 7:             break        if x < 2:            result = 4 * x            results.append(result)    return results assert imperative_style(range(10)) == [0, 4]`

By using the linked `Combinators` class, we can translate that to the following:

`from itertools import takewhile def fluent_combinator_style(xs):    return bw(xs).chain()\                 .R(takewhile, lambda x: x < 7)\                 .R(filter, lambda x: x < 2)\                 .R(map, lambda x: 4 * x)\                 .value()    assert fluent_combinator_style(range(10)) == [0, 4]`

The combinator methods work by altering the form of function calls. The `R` method transforms `bw(wrapped_value).R(takewhile, lambda x: x < 7)` into the call `takewhile(lambda x: x < 7, wrapped_value)`.

What I find interesting about this style is that it allows the end user of a class to add something that looks like a method to an object.

As I experimented using this class wrapping iterables, it began to remind me of Underscore.js. This resulted in a tiny (69 line) iterable wrapper `It`. Using `It`, we can redefine the above like so:

`from itertools import takewhile def it_style(xs):    return It(xs).chain()\                 .R(takewhile, lambda x: x < 7)\                 .filter(lambda x: x < 2)\                 .map(lambda x: 4 * x)\                 .value() assert it_style(range(10)) == [0, 4]`

Notice how `It` doesn't support `takewhile` out of the box, but the user can easily add it to the method chain. It provides flexibility on the level of the object instance, allowing the user to add functionality in a lightweight manner.