MartijnPieters answer is excellent. The only thing I would add is that this is called function composition
Giving names to these generics means you can use them whenever the need arises
from functools import reduce
def id(x):
return x
def comp(f,g):
return lambda x: f(g(x))
def compose(*fs):
return reduce(comp, fs, id)
# usage
# compose(f1, f2, f3, ..., fn) (val)
print(compose (lambda x: x + 1, lambda x: x * 3, lambda x: x - 1) (10))
# = ((10 - 1) * 3) + 1
# = 28
Sometimes you want it to look nicer though -
def seq (x): return lambda k: seq (k (x))
def fn1 (x): return x - 1
def fn2 (x): return x * 3
def fn3 (x): return x + 1
seq (10) (fn1) (fn2) (fn3) (print) # 28
# 10 9 27 28
And sometimes you want more flexibility -
from operator import add, mul, sub
def seq (x):
return lambda k, *v: seq (k (x, *v))
seq (10) (sub, 1) (mul, 3) (add, 1) (print) # 28
# 10 9 27 28
seq (1) (add, 2) (add, 3) (add, 4) (add, 5) (print) # 15
# 1 3 6 10 15