DEV Community

JM Santos
JM Santos

Posted on • Originally published at Medium on

2

Fusion in JavaScript

Nowadays it is extremely common to see the usage of Array methods such as Array.prototype.map(), Array.prototype.filter() and Array.prototype.reduce() to name a few in manipulating list data structures.

You can see a lot of method chaining such as a chain of Array.prototype.map() to process the transforming of a data, a chain of Array.prototype.filter() to include/exclude specific items in the array or a mixture of two (2) Array.prototype.map() and a Array.prototype.reduce() at the end. Those sorts of chainings are extremely common and that happens very often.

It's actually a great result having those sorts of chainings to manipulate data but there's a hidden cost on that in terms of performance and that's where the Fusion comes in.

⚡ Fuse 'em all

Fusion is a technique of combining pure functions — taking advantage of composition and removing the intermediary copies of data on each layer.

Let’s see an example comparing the non-fusion and a fusion approach.

// non-fusion approach
const data = [
1,
2,
3,
4,
5,
];
const add = (x) => x + 1;
const multiplyBy2 = (x) => x * 2;
const res = data
.map(add)
.map(multiplyBy2)
// [ 4, 6, 8, 10, 12 ] 

I would like to start noting that a mapper function that is passed on to the Array.prototype.map() should always, at least, handle it process in a pure manner to avoid unexpected results. Avoid using it and accessing outside variables or mutating another variable outside its lexical scope. Make it pure.

With the given example, you would think it’s well written and easily understandable but what’s the big deal? What is the hidden cost of having a chain of Array.prototype.map()?

Let’s discover it together by unpacking this chain.

// non-fusion approach
const data = [
1,
2,
3,
4,
5,
];
const add = (x) => x + 1;
const multiplyBy2 = (x) => x * 2;
const res = data
.map((i) => {
console.log('add mapper'); // called 5 times
return add(i);
})
.map((i) => {
console.log('multiplyBy2 mapper'); // called 5 times
return multiplyBy2(i);
})
// [ 4, 6, 8, 10, 12 ] 

Are you surprised? I am too at first.

Each chain of method whether it is Array.prototype.map(), Array.prototype.filter() or Array.prototype.reduce() comes with a cost. It will result in iterating the whole list again and again which will affect the performance especially if we are talking about large datasets.

You might think why not join the two (2) mapper functions in one call of Array.prototype.map()?

// non-fusion approach
const data = [
1,
2,
3,
4,
5,
];
const add = (x) => x + 1;
const multiplyBy2 = (x) => x * 2;
const res = data
.map((i) => {
console.log('add mapper'); // called 5 times
const sum = add(i);
const product = multiplyBy2(sum);
return product;
})
// [ 4, 6, 8, 10, 12 ] 

Yes we can join them in a single mapper to avoid chaining of Array.prototype.map(). That is actually a semi-fusion approach already. A full fusion approach is taking advantage of the composition.

I have a question for you, isn’t it inconvenient to manually pass the result from one function to the next function? What if the order is changed? How can we make it better?

Let’s now see how we can make this thing better by applying the Fusion technique.

// fusion approach
const data = [
1,
2,
3,
4,
5,
];
/**
*
* This utility function is often available on various
* functional libraries (i.e ramdajs)
* `pipe` is the opposite of `compose`
*/
const pipe = (...fns) => initialValue => fns.reduce((result, fn) => fn(result), initialValue);
const add = (x) => x + 1;
const multiplyBy2 = (x) => x * 2;
const res = data
.map(
pipe(add, multiplyBy2)
)
// [ 4, 6, 8, 10, 12 ] 

The pipe() utility accepts an infinite number of functions that it will run from left to right. Meaning that it will execute the functions, add() and multiplyBy2() from left to right and the result of the current function will be passed to the next one. That is kinda the shortcut instead of manually passing the result from one function to another function as we did on our previous example.

When a function is pure it means we can take advantage of composition. The composition is the act of combining pure functions to create a new single function. In our example, we created a new single function that is a composition of the two (2) pure mapper functions using the pipe() utility.

Now that we’ve applied the Fusion technique, our code will now handle even large datasets in a single iteration without duplicate iteration cost and also we’ve taken advantage of the composition in here which is great!

🤖 Bringing It All Together

Fusion is a great simple technique to have on our hands. It can help us when we are dealing with List data structures to take advantage of composition and also get the benefits in performance as well.

If we have a chain of maps together, composition is a much better way of declaratively saying what all of those steps are gonna be. Rather than three (3) .map calls, it would be preferrable from functional perspective to use composition. — Kyle Simpsons

If you are interested in checking it out more, here are some references:

Thank you for reading. I hope this will help you on your journey! ❤️

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (1)

Collapse
 
kafleenqalmar profile image
kafleenqalmar

In JavaScript, Fusion refers to combining multiple elements, libraries, or frameworks to enhance functionality and improve performance. It allows developers to integrate various features seamlessly, creating dynamic and interactive web applications. Just like how Plants vs Zombies Fusion Mod APK merges new plants, zombies, and gameplay mechanics for an upgraded experience, JavaScript fusion helps developers build more powerful and efficient web solutions by blending different technologies into one cohesive system.

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay