Reputation: 163
Consider I have an undetermined number of functions f, each one needing one argument and returning one result. How should I write a function "execute" taking the first argument as the number, and all the other arguments as functions to be applied to the result of each preceding function?
Here's my guess:
let plus1 = d => d += 1;
let plus2 = d => d += 2;
let write = d => document.write(d);
let execute = function(n,...functions){
functions.forEach((d)=>d(n));
}
execute(4,plus1,plus2,write);
I'm expecting 7 ((4+1)+2).
Thanks for your help!
Upvotes: 2
Views: 41
Reputation: 1993
The monoidal combination of two functions does exactly what you want: it propagates an argument through all the combined functions, the difference with your example is that all the results are later combined by another monoidal combination:
function monoidCombine(f, g) {
let ftype = typeof f;
let gtype = typeof g;
if (ftype === "function" && gtype === "function") {
return function(input) {
return monoidCombine(f(input), g(input));
};
}
if (ftype === "number" && gtype === "number") {
return f + g;
}
throw new Error(`No case for monoidCombine(${ftype}, ${gtype})`);
}
function execute(n, ...functions) {
return functions.reduce((f, g) => monoidCombine(f, g))(n);
}
execute(1, (x) => x + 3, (x) => x + 1);
// ^-- is equivalent to ((x) => x + 3)(1) + ((x) => x + 1)(1)
// so the result is 6
Upvotes: 1
Reputation: 386680
You could use Array#reduce
, which returns a result, while using a function with a given value.
let plus1 = d => d + 1,
plus2 = d => d + 2,
write = d => console.log(d),
execute = (n, ...fn) => fn.reduce((n, f) => f(n), n);
execute(4, plus1, plus2, write);
Shorter version as Yury Tarabanko suggested
let plus1 = d => d + 1,
plus2 = d => d + 2,
write = d => console.log(d),
execute = (...args) => args.reduce((v, f) => f(v));
execute(4, plus1, plus2, write);
Upvotes: 1