DEV Community

Discussion on: Transduction in JavaScript

Collapse
 
iquardt profile image
Iven Marquardt • Edited

Here is the identity transducer that does nothing but pretending to be a transducer:

// identity transducer (2x for illustrative purpose)

const foo = f => (x, y) => f(x, y);
//               ^^^^^^^^^^^^^^^^^ partially applied foo

const bar = f => (x, y) => f(x, y);
//               ^^^^^^^^^^^^^^^^^ partially applied bar

// reducer (or rather monoid operation)
const append = (x, y) => x.concat([y]);

// function composition
const comp = (f, g) => x => f(g(x));

[1,2,3,4,5].reduce(comp(foo, bar) (append), []); // [1,2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

The trick is that when we apply comp(foo, bar) (append), foo's f becomes the partially applied bar and bar's f becomes append. reduce then applies the partially applied foo with (x, y), which in turn applies the partially applied bar, which in turn applies append. This is the reason why transducers compose from left-to-right.

Collapse
 
jmaicaaan profile image
JM Santos

I'm honestly still having a hard time wrapping my brain when it comes to this. I mean, it's easy to understand normal compose and pipe flow of data. But, it's challenging for me to 100% track the flow of reducers in the transducers.
Thanks for the example. Took me a lot of reread :)

Collapse
 
iquardt profile image
Iven Marquardt

Ya, it's hard stuff. If we dig even deeper the reason for all this confusing behavior is the composition itself. comp doesn't return a value, but another composed function. I think you already mentioned this in your post. This is sometimes called abstraction over arity, because this new composed function expects more arguments than comp = (f, g) => x => f(g(x)) has originally required. Whenever this happens, the order of evaluation switches to left-to-right, not only with transducers.