To make our composition more readable and easier to name we are going to ceate a compose
function we can use to avoid having to manually nest our transducer calls.
We'll also go over semantically naming your compose
functions for extra readability.
The identity function works, because each reducer has only one argument? That is, in the first iteration when accumulator is x=>x then ...args is a single value?
I am confused
[1,2,3,4].reduce(isNot2Filter(isEvenFilter(doubleMap(pushReducer))), []) // this was [8]
[1,2,3,4].reduce(compose(isNot2Filter, isEvenFilter, doubleMap)(pushReducer), []) // this is [4, 6, 8]
so they are not the same result? Your compose calls the functions in reverse order to the nested example.
compose(f, g, h)(x) is resulting in h(g(f(x))) not f(g(h(x)))
[1,2,3,4].reduce(compose(doubleMap, isEvenFilter, isNot2Filter)(pushReducer), []) // this is [8]
@stephen you're right to be confused as there's a bug in the compose function, sorry about that.
accumulation
should be calling fn
instead of the reverse. I will update this over the weekend, thanks for pointing it out.
Well on the upside I really understand what it is doing now. :)
I was really scratching my head on that one, thanks @stephen!
For anyone reading this thread - the bug in the code has been fixed in the video.
Isn't x => x
unused in this case? It seems like each function that receives it is just expecting the single argument of reducer
, but we're adding x => x
as a second argument.
@greg - the identity function (x => x
) is purely there to make sure we don't throw an error if you call compose without any arguments, as you can't call .reduce
on an empty array without it. If you call compose with nothing but have the identity function there it will still work. I.e. calling compose()()
will be undefined.
If you don't mind that it throws an error - you can remove it.
Edit / update:
@greg you're spot on. Sorry was looking at my code samples not the code in the video. A bracket is in the wrong spot so the identity fn is not being passed as the second arg to .reduce
.
Correct compose fn:
const compose = (...functions) =>
functions.reduce((accumulation, fn) =>
(...args) => accumulation(fn(...args)), x => x);
I watched the last three videos twice because I was confused by the bug. And then I was confused because it was fixed and I didn't know why it was not confusing me anymore. :) Thanks for the update!
@Paul, in the video you're not passing x => x as the initial state to the .reduce, it's being passed on the reducer. So the function should still throw an error if invoked with an empty array. Is x => x the right approach when it doesn't match the signature of the input reducers?
Awesome stuff, quick question. What kind of sorcery are you using to show the value inline like a REPL?
@Divyendu I belive it is https://quokkajs.com/