const compose = (...fns) =>
fns.reduceRight((prevFn, nextFn) =>
(...args) => nextFn(prevFn(...args)),
value => value
);
Create the function, composed of three others:
const example = compose(
val => { console.log(1); return `1<${val}>`; },
val => { console.log(2); return `2<${val}>`; },
val => { console.log(3); return `3<${val}>`; }
);
Call the function:
example('hello')
Console output is:
3
2
1
"1<2<3<hello>>>"
It took me about an hour of stepping through the debugger to figure out what the point of spreading
...args
is (the resulting function has the same arity as the first function called in the chain, but all subsequent functions must have an arity of one). With a little tweak, you can use destructuring assignment to create a multivariate function chain, as long as all the composed functions have the same arity.Or if you want to generalize it so you can use it as a normal compose:
Of course you can always just cram all your arguments into an object and skip all the bother. :)
It's fascinating how the reducer creates closures over the inner function and the composed function unrolls them in reverse. If you haven't run it through a step debugger you really should!