What are pure functions?

This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.

Subscribe: RSSApple PodcastsGoogle PlayOvercast

What are pure functions? I explore the definition, the term itself, and why functional programmers like pure functions.

Transcript

Eric Normand: What is a pure function? Hello, my name is Eric Normand. These are my thoughts on functional programming. Please subscribe, and you'll get all the new episodes when they come out.

Pure functions, this is a term that I think is a little unfortunate because the word pure implies virtue, cleanliness, and hygiene. It is not really about being hygienic. Pure functions originated, as far as I could research, with compiler design.

If you could identify a function, let's say a C function, in your code, you're the compiler, you're identifying that this function only depends on the arguments, so the return value is just some combination of the arguments.

That would give you a lot of leverage for optimizing in a way. It's a pure function. It doesn't depend on any variable. C variables are mutable, so they could change at any moment.

If you could see that this function is always going to return the same value no matter when you run it, no matter what else is running because it's just based on the arguments, so you call it with the same arguments, it's going to give you the same value.

You could run that function at compile time and replace that call to it with its return value at compile time. Just like you could say, "Well, I know 1+1 is 3. I'm going to just replace this 1+1 with a 3 and save a little bit of computation," you can do the same with a pure function.

This term stuck in programming it doesn't mean quite that anymore. What it means is a function that does not have any side effects. That's a whole other term that's unfortunate.

What are side effects? Some side effects that you might find are modifying a mutable variable or sending an email, reading from the database, updating some key-value store somewhere, something like that.

Every time you run it, something is going to happen that can change the world and have some effect on the rest of the world, maybe just the rest of your program. A pure function it might not just be a combination of the arguments.

For instance, it might read a constant. It might have some other input but it's an immutable input, so it's always going to be the same. It also has this same property that in theory at compile time, you could replace a call to this with the return value.

That property is actually called referential transparency. You can take a call to the function and replace it with its return value. The compiler can do that if it's a pure function that's referentially transparent. They're interchangeable. You could say it's a pure function or it's a referentially transparent function. They're interchangeable.

Functional programmers also want to be able to do mathematical reasoning. They use the term pure function to reference mathematical functions, which are different from, say, a JavaScript function. In a JavaScript function, you can do any calculation you want, but you can also send off AJAX requests.

You can read input. You can do any kind of code you want, whereas a mathematical function is much more restricted. It defines a relation between the argument values and the return value. They don't call it that. They call it the domain and the range. The domain is the arguments, and the range is the return value.

There's a relationship between the arguments, relationship meaning a mathematical relationship. You might say, "Well, this adds the arguments and then multiples them by three." That's the return value. The relationship is some formula to add and multiply and then return it.

That mathematical function is also referentially transparent. Functional programmers use this term, pure function, to mean that it's a function that doesn't have any side effects, which implies that it's referentially transparent. It means it's timeless in the same way that mathematical function is timeless.

For instance, addition is timeless. It's never going to change. You can run 3+7 as many times as you want, you're always going to get 10. If you can write a pure function in your code, you're going to have that similar property. This is important. It doesn't matter when you run it or how many times you run it.

Every bit of code we have, in theory, we want to be able to test it. We want to be able to scale it out to multiple machines, at least multiple threads on our system. If you say, "It doesn't matter when you run it or how many times you run it," that means that I can run it in multiple threads.

It doesn't matter when I run it or how many times. I can run it a hundred times and a hundred different threads I'll always get the same answer.

I can run it on my test server. I can test it. When you test it, you need to run it a million times, a hundred times, a thousand times. It's going to run a lot of times. Imagine if you had a function that sent an email every time it was run.

You couldn't test it the same way. You couldn't test it a million times. You wouldn't want to run that in multiple threads at the same time. Possibly. It depends on how you implement it, but you're going to have to think about it.

What's going to happen if I try to send emails all at the same time in multiple threads on multiple boxes? How do they know that they're not going to send the same email twice? There's questions there that are brought up.

Functional programmers recommend using more pure functions because they're way easier to think about. They're easier to test because they don't have any side effects that you don't have to look there when you are trying to figure out why you're sending too many emails. You don't have to look there. That's not where the problem is.

This has been my explanation of pure functions. I'm sorry. It's a bad term. I don't like the term for a couple of reasons. One is what I mentioned at the beginning that it has this implication of virtue that it just puts people off.

Once you understand the definition, you understand it's not about that. It's a pure function, meaning it's just a function is really what they're trying to say in a mathematical way. It's just a mathematical function. It's not a mathematical function and it sends an email.

I don't like that word pure. It has too many connotations. Then function. The thing is not every language uses functions. For instance, Java until recently...Now they have lambdas. They call them lambdas. Before that, they just had methods. That's the closest thing you have. Is it a pure method? It doesn't make sense.

It excludes languages that don't have functions, that have something that could work just as well. I think that you could do functional programming in any language, including assembly if you really wanted to. It's not good to call them functions, because you don't have functions in every language.

My name is Eric Normand. Please subscribe so that you can get every episode as it comes out. You can also get in touch with me if you have a question or you want to disagree with me, give me a better definition of functional programming. Maybe I got the history wrong.

My email is eric@lispcast.com. You can also find me on Twitter, @ericnormand. I do try to respond to people talking to me on Twitter. Also, on LinkedIn, you can find me just search Eric Normand and Clojure, and I should be right there up at the top. I'll see you next time. Take care.