DEV Community

Kevin Downs
Kevin Downs

Posted on

What's a Pure Function?

This week I was exploring more interview prep materials and stumbled upon the topic of Pure Functions in JavaScript. I thought it would be a good concept to review because likely other people are just as confused by them at first as I was. My first thoughts when I learned of the concept of pure functions were something along the lines of "Wait, does that mean there are impure functions?" and "Does that mean one is preferable over the other?".

The immediate answer to those questions is "Yes, a function that is not pure is by definition impure." and "Kind of, depending on the situation.", but let's take a step back. Before we dive into talking about types of functions, we should probably just talk about functions in general first. Let's pull out our handy dandy documentation and look at some definitions.

MDN documentation defines functions as so:

Functions are one of the fundamental building blocks in JavaScript. A function is a JavaScript procedure—a set of statements that performs a task or calculates a value. To use a function, you must define it somewhere in the scope from which you wish to call it.

Okay, so a function is a bit of code that takes an input, does some things, and outputs a value. How does that help us? Well, the key to determining whether a function is pure depends completely on what is happening during that "do something" part. Now that we have that little bit out of the way, let's talk about what exactly a pure function is.

There are only two requirements for function to he considered pure:

  1. Same input - same output. This means that as long as the same input is passed into a function, the same output will always be returned.
  2. No side effects. This means that the function does not change anything outside of itself. No network requests, no mutating outside data, no writing to disk, etc.

Take a look at the two functions below and see if you can figure out which one is pure and which one is not.

// Function 1

function multiply(num, mult){
   return num * mult;
}

// Function 2

var mult = 2;

function multiply(num){
   return num * mult;
}

If you guessed that the first function is the pure one, you'd be correct. multiply(2,2) will return 4 every single time it is run and does not perform any outside mutations. This is the essence of a pure function.

However, the second function relies on outside data for its computation. Because we have to rely on the global mult variable, multiply(2) could return 4 on one call, 6 on the next, and so on. I think you can begin to see some situations in which pure functions may be considered "better" than impure ones.

Pure functions are not always the best solution to a problem. Sometimes we want to change outside data, make a network request, or perform some other operation outside of a pure mapping computation. That's one of the reasons the answer to "Are pure functions better" is both yes and no. It depends on the context.

The thing about pure functions, and what often times makes them the better solution, is that they are simple in their use. That is, you needn't worry that a pure function will cause problems elsewhere because it doesn't touch anything outside of itself. This creates less room for bugs and side effects, and also makes refactoring easier as you only have to be concerned with the code inside the function.

In summary, pure functions are a great way to tidy up your code and they are a great way to keep your code scalable and bug free. However, they aren't always the best tool for the job. A good balance and the proper utilization of pure and impure functions can make for better and more durable code.

Check out these resources if you'd like to learn more:

Functions - MDN
JavaScript: What Are Pure Functions And Why Use Them?
What Is a Pure Function in JavaScript?

Also feel free to follow me elsewhere on Twitter, Github, or LinkedIn.

Top comments (6)

Collapse
 
pentacular profile image
pentacular

Okay, so a function is a bit of code that takes an input, does some things, and outputs a value.

I think this is the crux of what makes things confusing. :)

A function is a mapping between arguments and results -- it doesn't do anything.

A procedure is a sequence of operations that happen over time.

Where it gets confusing is that we usually implement functions with procedures, because most programming languages can't express functions, and so people got into the habit of confusing the names, and so in many systems we ended up calling procedures functions.

Which ends up with a 'pure function' being a procedure which implements a function, as opposed to a procedure which doesn't implement a function, which people now call an 'impure function' in contrast.

Personally, I try to talk about functions and procedures, which makes it all straight-forward. :)

Collapse
 
phantas0s profile image
Matthieu Cneude

That's a very good point.

It's a good definition for the function in mathematics (mapping), but the sense in programming evolved beyond that. Now, a function is not only a mapping but a series of instruction.

Many different concepts in programming have now the same name (for example encapsulation and information hiding, which are normally different concepts), and I'm not sure it's a good thing. We lose a lot of nuance.

Collapse
 
pentacular profile image
pentacular

It's not an evolution -- it is a devolution, because early programming languages could not reason effectively about functions.

So they ended up using algorithms (procedures that implement functions) instead, because they could reason about them in a mechanical sense.

Unfortunately when we reason about them in a mechanical sense it becomes very difficult to prove invariant relationships about them, so a lot of the work compilers do is to try to guess what function a procedure might implement, so that it can avoid implementing the procedure. :)

More recently we have programming languages which can reason effectively about functions, which is why functional programming is becoming more popular.

(Although a lot of what people call functional programming is just the use of higher order procedures)

Thread Thread
 
phantas0s profile image
Matthieu Cneude

More recently we have programming languages which can reason effectively about functions, which is why functional programming is becoming more popular.

Do you think about Haskell? The only functional programming languages I used are Scheme and Clojure.

Thread Thread
 
pentacular profile image
pentacular

I think that Haskell is a good example, Miranda and Clean also.

Prolog and Mercury also, although things like the cut operator make it a bit more complicated.

Scheme and clojure are both procedural languages, with good support for function composition.
Clojure has good support for immutable data structures, but that's not quite what we're after here.

The ACL2 theorem prover is probably the closest in the lisp family.

C++ is gradually trying to get its toes wet with things like constexpr functions, and templates, but ... :)

Which is not to say that procedures and algorithms are bad, and functions are good -- it's just that procedures are easy to execute and functions involve harder proof-work -- there are good economic reasons for the bias toward procedures in programming languages.

Collapse
 
mohsenalyafei profile image
Mohsen Alyafei

Thanks Kevin for the post. In the last utility I am developing, I found that the only best way to achieve code optimization and efficiency is the use of impure functions.