Skip to content

What is a pure function?

Daisho Komiyama edited this page Aug 10, 2019 · 1 revision

Okay, let's review where we've been so far, we started with; a pure function needs to take some inputs and return an output, so where we started, the very, very beginning. That was good but not good enough. And then we said, well no, actually it needs to have a relationship between the inputs and the outputs, which was better but still not good enough. And then we said, well no, actually they need to be direct inputs and direct outputs, which was good but not good enough. And then we said, well no, actually they don't have to be direct inputs, they can be indirect at long as they're not changing. Remember, we can close over stuff as long as not changing, which was even better definition, but still not good enough. And they we said, well, actually the real thing is, it's the function call that every time I call the function with the same inputs, I should get the same output. If that's true, then I have a pure function call, right? Even better definition, but still not complete.

Here's the full, canonical, complete definition for a pure function, and specifically for a pure function call, remember, we're focused on the function call.

1  function repeater (count) {
2     return memoize(function allTheAs () {
3         return ''.padStart(count, 'A');
4     });
5  }
6
7  const A = repeater(10);
8
9  A(); //'AAAAAAAAAA'
10 A(); //'AAAAAAAAAA'

Line 9 is a pure function called because or if. I could take the return value of that function call, and replace the function call with the return. In other words if A was somehow being used somewhere in the program, like it was part of some other expression, which always returns the string, If I take the string AAAAA and literally just replace the function call with that value... If I could do that and not affect any of the rest of the program, then I have a pure function call. There's a very special term, again, if you say this to your co-workers after the course, you're gonna sound much smarter, so use it, use it with your boss. The term is called referential transparency. Sounds cool to say doesn't it? A function call is pure if it has referential transparency. Referential transparency means, a function call can be replaced with its return value and not affect any of the rest of the program.

Kyle Simpson: Now it turns out referential transparency, that's a really key idea, it turns out that in a language like, for example, Haskell, the granddaddy of functional programming, referential transparency is a key characteristic of the language end of the compiler indeed.

Because in Haskell, when you write functions they're always pure, which means they always have referential transparency, which means that because that's a guarantee of the language, the compiler can take advantage of that. It literally normalizes everything, because it can do that for free. It can literally replace other function calls with the inline result of the previous function call, they do that automatically for free because they have that guarantee of the language, we do not have that in JavaScript.

So, does referential transparency only matter if the compiler can do it? Some would say yes, but I would say no. In a bigger sense, the real benefit of referential transparency is actually to the reader of the code. Consider any function call in a program that is indeed a pure function call.

The reader of your code reads line 11, and they go and they compute it, they say, okay, I know that line 11 is this value, the value 42, or whatever. Everywhere else that they see that exact same function call anywhere later in the program with the same inputs, do they need to go re-compute the result?

No, because what are they gonna do? They're gonna referentially swap out the function call for the result they've already computed in their head, and what's that gonna do? It's gonna free up their brain power to focus on other, more important parts of your app. So referential transparency, while it matters a lot to the compiler in something like Haskell, for us in JavaScript, the reason it matters is because it puts the responsibility on you, the author of the code.

To make it as easy as possible for the reader of your code, which includes your future self, to be able to look at a line and know exactly what it's gonna do, and then not have to redo that work over and over, and over again. I said at the outset of this course, the best code is the code that didn't have to be read in the first place.

Cuz I looked at it and said, I've already done that, I don't need to do that. That's why function purity matters so much. It's like we're building up this pyramid, and this is the base stone of the pyramid, and if you take it out everything else would crumble.

You cannot have anything else in functional programming unless you get the value and the importance of function purity. Function call purity specifically.

Clone this wiki locally