Codementor Events

Why Pure Function?

Published Apr 24, 2019Last updated Oct 20, 2019

Introduction

A pure function is, given the same input, the function will always return the same output. To explain this as in mathematical terms: For every input returns a single output, every single time.

pasted image 0.png
A pure function has no impurities. Meaning the actions/elements in the function that are responsible for that function to produce different response for the same inputs.
For example:

function logSomething(something) {
    const dt = (new Date())toISOString();
    console.log(`${dt}: ${something}`);
    return something;
}

This logSomething() function has two sources of impurity: It creates a Date() and it logs to the console. So, not only does it perform IO, it also gives a different result every millisecond that you run it. Therefore the function is not pure function.
Dependency injection is one of the many ways with which you can achieve pure functions. Lets discuss how pure functions can be helpful with dependency injection.

Dependency Injection

In this approach, we basically take any impurities in our code, and put them into function parameters. Then we can treat them as some other function’s responsibility. To explain what I mean, let’s look at the code before. How could we make the above function pure? With dependency injection, we take any impurities and make them a function parameter.

function logSomething(d, cnsl, something) {
    const dt = d.toIsoString();
    return cnsl.log(`${dt}: ${something}`);
}

Then to call it, we have to explicitly pass in the impure bits ourselves:

const something = "Some Text";
const d = new Date();
logSomething(d, console, something);

You might think that all we’ve done is put the problem one level up. The whole program will still have the same amount of impurities. And you’d be right. But notice something about logSomething() function. If you want it to do something impure with that function, you have to make it impure first, right?
For example we could just as easily pass different parameters:

const d = {toISOString: () => '1865-11-26T16:00:00.000Z'};
const cnsl = {
    log: () => {
        // do nothing
    },
logSomething(d, cnsl, "Random Text!");
};

Now, our function does nothing. But it still is completely pure. If you call it with those same parameters, it will return the same thing every single time. And that is the point.
Let’s look at another example. Imagine we have a username in a form somewhere. We’d like to get the value of that form input:

function getUserNameFromDOM() {
    return document.querySelector('#username').value;
}
const username = getUserNameFromDOM();

In this case, we’re attempting to query the DOM for some information. This is impure, since document is a global object that could change at any moment. One way to make our function pure would be to pass the global document object as a parameter. But, we could also pass a querySelector() function like:

function getUserNameFromDOM($) {
    return $('#username').value;
}
const qs = document.querySelector.bind(document);
const username = getUserNameFromDOM(qs);

Again, you may be thinking there is no meaning. All we’ve done is move the impurity out of getUsernameFromDOM(). It hasn’t gone away. We’ve just put it in qs(). It doesn’t seem to do much other than make the code longer. Also, instead of one impure function, we have two functions, one of which is still impure.

Yes, but if we want, in this way, we can keep pushing that impurities further and further out. Eventually, we push them right to the surface of our code. So we end up with a thin shell of impure code that wraps around a well-tested, predictable core. As you start to build larger applications, this will starts to matter a lot. Because in the case of occurrence of a bug, you will hardly ever debug deep in your code. You will have to test/debug only the shell. And that will be massively efficient in the long run.

Conclusion

Dependency injection is also not perfect. One of the main disadvantages of this is that you end up with lengthy function signatures.
For Example:

function app(doc, con, ftch, store, config, ga, d, random) {
    // Application code goes here
 }
app(document, console, fetch, store, config, ga, (new Date()), Math.random);

This article was rather about why pure functions are important and showcasing it using one of the methods as an example.

***this article was derived from different articles on the internet
Discover and read more posts from Siam Hossain Anik
get started
post comments1Reply
violetevergarden
5 years ago

thanks a lot! the explanation is to elaborate and the images made it even easier to understand