I have been reading up on transducers and playing around trying to grasp the concept. I now understand them a bit, but during my fiddling, I came across something very peculiar that has me dumbfounded. I'm hoping someone can explain what I'm missing.
I have 2 transducers that have the signature: reducer -> reducer
I also have a simple compose function: const compose = (f, g) => x => f(g(x))
When I compose the 2 transducers:
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)
I would expect the evaluation to be from right to left, in this case applying the mapping transform before the filtering. Instead, the filtering is applied first (which gives the expected answer).
But f(g(x)) runs f of the result of g(x), so my result should reflect:
filteringReducer(lessThanThreePredicate)(mappingReducer(multiplyTransform)
(concatTransducer))
But instead it reflects (correctly):
mappingReducer(multiplyTransform)(filteringReducer(lessThanThreePredicate)
(concatTransducer))
(See code below)
Why??!! (I suspect I'll make a quantum leap in understanding once someone explains to me what's happening here).
const filteringReducer = predicate => transducer => (result, input) =>
predicate(input) ? transducer(result, input) : result
const mappingReducer = transform => transducer => (result, input) =>
transducer(result, transform(input))
const compose = (f, g) => x => f(g(x))
const concatTransducer = (a, b) => a.concat([b])
const lessThanThreePredicate = x => x < 3
const multiplyTransform = x => x * 100
const filterLessThanThreeAndMultiply = compose(
filteringReducer(lessThanThreePredicate),
mappingReducer(multiplyTransform)
)
const result = [-2, -1, 0, 1, 2, 3, 4].reduce(
filterLessThanThreeAndMultiply(concatTransducer),
[]
)
console.log('result ', result) // [-200, -100, 0, 100, 200]