You've chained data through a few transformations — trim a string, lowercase it, then split it. Writing split(lower(trim(input))) reads inside-out, and it gets worse with every step. Function composition gives you a single reusable function built from the pieces, applied right-to-left so the picture matches the math: compose(f, g, h)(x) === f(g(h(x))).
Implement a compose function that takes any number of unary functions and returns a new function. Calling that new function with an input runs the rightmost function first, feeds its result into the next, and so on, returning the final value. See MDN on function composition for background.
function compose(...fns) {
// returns a new function that, when called with `x`,
// applies the rightmost fn to `x` and pipes results leftward
}
const addOne = (n) => n + 1;
const double = (n) => n * 2;
const f = compose(addOne, double);
f(3); // 7 — double(3) = 6, then addOne(6) = 7
const shout = compose(
(s) => s + '!',
(s) => s.toUpperCase(),
(s) => s.trim(),
);
shout(' hello '); // 'HELLO!'
compose()(x) must return x unchanged.compose(f)(x) must return f(x).fns array.