What are Transducers?
A quick noob intro: transducers are composable and efficient data transformation functions which doesn’t create intermediate collections.
Here’s a visualisation to show the difference between array built-ins and transducers.
Why use them?
The above visualisation means that given transformations like map, filter and reduce we want to compose them together to pipe every piece of data through them step by step. But the following is not this kind of composition:
Instead we want something like this:
const transformation = compose(map(fn1), filter(fn2), reduce(fn3));
This way we can reuse the transformation and compose it with others. But the problem is that map, filter and reduce functions have different signatures. This is why all of them need to be generalised and it can be done in terms of reduce.
Code examples from the article
map and filter, and how they can be combined together:
map and filter can be implemented using reduce. Here’s map implementation:
Let’s extract incrementing function to allow it to be passed into reducer:
More usage examples of map reducer:
filter implementation using reduce:
Again, extract predicate function, so it can be passed from the outside:
Combine both reducers together:
Similar to what you usually do with built-in array methods:
Here are both reducers again and both of them are using array push as a reducing function:
push and + are both reducing functions, they take initial value and input, and reduce them to a single output value:
Let’s extract reducing function, so it can be also passed from the outside:
Here’s how reducers can be used now:
The type of reducers is result, input -> result:
Composition of reducers has the exact same type:
So it also can be used as a reducer:
Let’s use R.compose from Ramda library for better readability:
More complex example:
Finally let’s wrap it into transduce helper function: