-
-
Save neftaly/6e11268f1cd230094c81 to your computer and use it in GitHub Desktop.
| const compose = (...args) => initial => args.reduceRight( | |
| (result, fn) => fn(result), | |
| initial | |
| ); |
Hey, I didn't see your comment earlier, sorry. I like your simplification, but this is actually intended behaviour, and operates the same way as Ramda.
The idea is that a composition will always return a fn. This isn't an artificial stylistic rule, but a behaviour described by the type signature I haven't bothered to write 😄
While less elegant, an extension of the idea allows multiple args to be provided to the first fn (like in Ramda).
const compose = ([ firstArg, ...restArgs ]) => (...initial) => restArgs.reduceRight(
(result, fn) => fn(result),
firstArg(...initial)
);
// Same thing, written differently
const compose = (...args) => (...initial) => args.reduceRight(
(result, fn) => [ fn(...result) ],
initial
)[0];
const example = compose(
z => z.toUpperCase(),
(a, b) => a + " " + b
)("foo", "bar");That said, your way is perfectly valid if you're just borrowing ideas from functional JS programming and haven't fully bought into the whole thing.
Type signature is something like compose :: (c, b, a, ...) -> (x, y, z, ...) -> ...(c(b(a(x, y, z, ...))))
const compose = ([ firstArg, ...restArgs ]) => (...initial) => restArgs.reduceRight(
(result, fn) => fn(result),
firstArg(...initial)
);this implementation is broken in sense that for compose right most function can be any arity, and in this example its left most
// Same thing, written differently
const compose = (...args) => (...initial) => args.reduceRight(
(result, fn) => [ fn(...result) ],
initial
)[0];this implementation will be broken if any function inside compose will return array as a value, so next function will take this array not as first argument, but as arguments as a whole
Working as intended implementation should look like this:
const compose = (...fns) => {
const [tailFn, ...restFns] = fns.reverse();
return (...args) => restFns.reduce(
(value, fn) => fn(value),
tailFn(...args)
);
};
const pipe = (...fns) => compose(...fns.reverse());Or other way around
const pipe = (headFn, ...restFns) => (...args) => restFns.reduce(
(value, fn) => fn(value),
headFn(...args)
);
const compose = (...fns) => pipe(...fns.reverse());@iamstarkov How does the functions handle functions with two arguments? Could you give me an example or how to modify the code so it handles them?
Hello, here's my version https://gist.github.com/WaldoJeffers/905e14d03f4283599bac753f73b7716b. Does it cover your use cases ?
This page was the first to come up when searching for "es6 compose".
Looking at the example code I think an improvement could be made.
The existing code:
Does not account for the first use.
Will Incorrectly return a function expecting "inital".
I propose a simplification:
Not only have we reduced (<- pun) the function, but we now will get our initial value back on the first call.
Thoughts?