I'm following an article about Transducers in JavaScript, and in particular I have defined the following functions
const reducer = (acc, val) => acc.concat([val]);
const reduceWith = (reducer, seed, iterable) => {
let accumulation = seed;
for (const value of iterable) {
accumulation = reducer(accumulation, value);
}
return accumulation;
}
const map =
fn =>
reducer =>
(acc, val) => reducer(acc, fn(val));
const sumOf = (acc, val) => acc + val;
const power =
(base, exponent) => Math.pow(base, exponent);
const squares = map(x => power(x, 2));
const one2ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
res1 = reduceWith(squares(sumOf), 0, one2ten);
const divtwo = map(x => x / 2);
Now I want to define a composition operator
const more = (f, g) => (...args) => f(g(...args));
and I see that it is working in the following cases
res2 = reduceWith(more(squares,divtwo)(sumOf), 0, one2ten);
res3 = reduceWith(more(divtwo,squares)(sumOf), 0, one2ten);
which are equivalent to
res2 = reduceWith(squares(divtwo(sumOf)), 0, one2ten);
res3 = reduceWith(divtwo(squares(sumOf)), 0, one2ten);
The whole script is online.
I don't understand why I can't concatenate also the last function (sumOf
) with the composition operator (more
). Ideally I'd like to write
res2 = reduceWith(more(squares,divtwo,sumOf), 0, one2ten);
res3 = reduceWith(more(divtwo,squares,sumOf), 0, one2ten);
but it doesn't work.
Edit
It is clear that my initial attempt was wrong, but even if I define the composition as
const compose = (...fns) => x => fns.reduceRight((v, fn) => fn(v), x);
I still can't replace compose(divtwo,squares)(sumOf)
with compose(divtwo,squares,sumOf)
Finally I've found a way to implement the composition that seems to work fine
const more = (f, ...g) => {
if (g.length === 0) return f;
if (g.length === 1) return f(g[0]);
return f(more(...g));
}
Here it is another solution with a reducer and no recursion
const compose = (...fns) => (...x) => fns.reduceRight((v, fn) => fn(v), ...x);
const more = (...args) => compose(...args)();
usage:
res2 = reduceWith(more(squares,divtwo,sumOf), 0, one2ten);
res3 = reduceWith(more(divtwo,squares,sumOf), 0, one2ten);
full script online