Skip to content

Instantly share code, notes, and snippets.

@jgomo3
Last active April 5, 2018 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgomo3/5731ec71d6893697f7516912b2be9ad5 to your computer and use it in GitHub Desktop.
Save jgomo3/5731ec71d6893697f7516912b2be9ad5 to your computer and use it in GitHub Desktop.
Function composition and piping (or chaining) using reduce
from functools import partial
from functools import reduce
def _chain(order, *functions):
ordered_functions = list(order(functions))
first_fn = ordered_functions[0]
rest_fn = ordered_functions[1:]
def _apply(x, f):
return f(x)
def composite(*args, **kwargs):
return reduce(_apply, rest_fn, first_fn(*args, **kwargs))
return composite
o_ = partial(_chain, reversed)
o_.__doc__ = "Function composition: o_(f1, ..., fn)(x1, ..., xm) = f1(...(fn(x1, ..., xm)))"
p_ = partial(_chain, lambda _:_)
o_.__doc__ = "Pipe the functions: p_(f1, ..., fn)(x1, ..., xm) = fn(...(f1(x1, ..., xm)))"
# Test
import unittest
class TestKnowCases(unittest.TestCase):
def setUp(self):
self.add = lambda a, b: a + b
self.inc = lambda x: x + 1
def test_know_composition(self):
add_and_increment = o_(self.inc, self.add)
self.assertTrue(add_and_increment(1,2), 4)
def test_know_piping(self):
add_and_increment = p_(self.add, self.inc)
self.assertTrue(add_and_increment(1,2), 4)
def test_composition_equals_piping(self):
add_and_increment_o = o_(self.inc, self.add)
add_and_increment_p = p_(self.add, self.inc)
self.assertEqual(
add_and_increment_o(1,2),
add_and_increment_p(1,2))
def test_idempotence_of_composition(self):
add_and_increment_o = o_(self.inc, self.add)
self.assertEqual(
add_and_increment_o(1, 2),
add_and_increment_o(1, 2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment