What is pure function? – DEV Community

Understanding Functional Programming
Functional programming is a programming style or paradigm that focuses on building software by creating and combining functions. Think of it like this: you write small, self-contained pieces of code (functions) that take an input, perform some operations, and then produce an output. A core idea is that for the same input, you will always get the same output, making the code predictable.
Why Use Functional Programming?
- Reusable: Functions are designed to be independent, meaning you can easily reuse them across different parts of your code or in various modules, as long as you need their specific output.
- Stateless: Functional programs aim to be “stateless.” This means a function’s output depends solely on its inputs, not on any changeable internal or external state. No matter how many times you run a function with the same input, you’ll always get the identical output.
- Easier to Test: Because functions are self-contained, predictable, and don’t cause side effects (changes outside themselves), they are much simpler to test and debug.
- Concurrency Friendly: The stateless and immutable nature of functional programming makes it easier to write code that runs correctly in parallel, reducing common issues found in multi-threaded applications.
Pure Functions
Functional programming relies heavily on a concept called pure functions. So, what exactly makes a function “pure”? A pure function must strictly adhere to these 3 rules:
1.Always returns a single value. A pure function must consistently produce exactly one output value.
Bad Example:
static char getFirstCharacter(String s) {
return s.charAt(0);
}
This is “bad” because, depending on whether the string s is empty or null, it could either return the first character or throw an error. This means it has multiple possible outcomes for its “return.”
Good Example:
static int increment(int x) {
return x + 1;
}
This is “good” because it predictably returns a single value: the input x plus one.
2.Calculates the return value based only on its arguments (inputs). The output of a pure function should be determined only by the values passed into it as arguments. It must not depend on or be influenced by any external data, variables, or system state that could change.
Bad Example:
static double randomPart(double x){
return x + Math.random();
}
This is “bad” because Math.random() generates a different random number each time it’s called. This makes the function’s return value unpredictable even with the same x input. This unpredictable change caused by something outside the function is called a “side effect.”
Good Example:
static int add(int a, int b){
return a + b;
}
This is “good” because for the same inputs a and b, it will always return the same sum.
3.Doesn’t change (mutate) any existing values or external state. A pure function must not modify any of the data passed into it, nor should it alter any variables or objects outside of its own scope. It produces new data rather than changing old data.
Bad Example:
public static void addTag(User user, String tag) {
user.tags.add(tag);
}
While this code works, it’s considered “bad” in a pure functional context because it directly modifies the user object that was passed in. If you call this function multiple times with the same user object, the user.tags list will continually change. This modification of an existing object is known as mutating a value (a side effect) and violates rule #3.
Good Example:
public static User addTag(User user, String tag) {
List<String> newTags = new ArrayList<>(user.tags);
newTags.add(tag);
return new User(newTags);
}
This is “good” because the addTag function does not alter the original user object. Instead, it creates a new list (newTags), adds the new tag to that new list, and then returns a new User object that incorporates these changes. The original user object remains completely unchanged, thus avoiding any side effects and adhering to the “no mutation” rule.
Example of a Pure Function:
Here’s an example of a function that clearly follows all 3 rules of a pure function:
public static int calculateTotalPrice(int pricePerItem, int quantity, int discountPercent) {
int total = pricePerItem * quantity;
int discount = total * discountPercent / 100;
return total - discount;
}
public static void main(String[] args) {
int result = calculateTotalPrice(100, 5, 10); // 100 * 5 = 500 - 10% = 450
System.out.println("Total price after discount: " + result);
}
If a function misses any of these three rules, it becomes an impure function. While impure functions can exist in your code (especially due to the third rule), they might not fully align with the goals of functional programming.
Handling Large Data and Performance
Sometimes, when dealing with large amounts of data, like lists or collections, copying everything to create a new, immutable version can hurt performance. In such cases, you might have to accept making the data mutable to solve the performance issue. This is a trade-off you need to consider. If performance isn’t affected, it’s always better to keep data immutable.
Some languages (like JavaScript or Scala) have built-in collections that are immutable by default, so you don’t need to manually copy them to prevent mutation. but Java need to be copy to a new collection for immutable.
Here’s an example of creating a new collection inside a function to prevent mutating the original:
public static List<Integer> doubleAllValues(List<Integer> numbers) {
List<Integer> result = new ArrayList<>(); // Create a new collection to avoid changing the original
for (int num : numbers) {
result.add(num * 2);
}
return result;
}
public static void main(String[] args) {
List<Integer> original = new ArrayList<>();
original.add(1);
original.add(2);
original.add(3);
List<Integer> doubled = doubleAllValues(original);
System.out.println("Original list: " + original); // Output: Original list: [1, 2, 3] (Not changed)
System.out.println("Doubled list: " + doubled); // Output: Doubled list: [2, 4, 6]
}
Understanding pure functions and their 3 rules is a great starting point for writing functional code. Pure functions are just one piece of the puzzle in functional programming; there are many other concepts to explore! We’ll share more about those later.
I hope you enjoy this content. if you have any concern or question you can ask me thank you.
Reference
https://www.amazon.com/Grokking-Functional-Programming-Michal-Plachta/dp/1617291838 In Part 1 Chapter 2 & 3