A function is considered a pure function if the result depends only on the arguments, and it has no βside effectsβ like modifying an argument or outputting something. The only result of calling a pure function is the return value.
Letβs consider an increment function that changes a time like 3:48 to 3:49 or 11:59 to 12:00. We have two ways we could design the function. It could be a pure function that returns a new time or a modifying function that takes a time by reference and changes it.
This version takes a Time by const reference and calls it t. It then makes a copy of the time, modifies the copy, and returns it. We could also write a pure function using pass by value. With pass by value, the parameter is already a copy of the argument that was passed in. So we donβt need to explicitly make a copy of the parameter to modify:
This version takes a Time by reference and modifies it. It does not return anything new - the whole point of this function is itβs βside effectβ of changing the parameter.
Either version could be used to build any program we like. If you wanted to change an existing time with the pure version, you could just use an assignment to store the new value into an existing variable:
Time time = { 11, 59 };
// Make a copy of the time and modify the copy
Time newTime = time;
incrementPure(newTime);
// time is still 11:59, newTime is 12:00
So which is best? Pure functions help to maintain the abstraction of a function. When a function does nothing but give us an answer, we donβt have to worry about what else might be going on behind the scenes. You do not ever have to worry about there possibly being hidden interactions between various functions because one function made some hidden change to the programβs state that then changes how the next function behaves. In fact, there are programming languages, called functional programming languages, that only allow pure functions. These languages are designed to make it easier to write bug free code, and to write tests to prove that the code is correct by compltely eliminating the chance of side effects.
However, pure functions can be less efficient. Our pure increment function must make a new Time struct each time we call it. This is more work than just changing a number or two in an existing struct, which the modifying version does. In situations where we have a large struct with many member variables and want to have a function that only changes one of the variables, it can be wasteful to make a copy.
In general, you should favor pure functions for smaller structs (where the efficiency differences arenβt as extreme) or situations that clearly imply that a new value or copy are being made. Favor modifying functions when you make are making small changes to a large existing struct or the situation clearly involves changing an existing value and then not caring about the old value. Do try to stick to one approach or another. Writing a function that modifies the input and returns a new value
Modifying functions tend to make the code more complex. You have to worry about what the function is doing to the data and how that might affect other parts of the program.