Skip to content

What are Pure & Impure Functions?

This lesson details pure and impure functions with various examples for understanding.

Gopi Gorantala
Gopi Gorantala
4 min read

Table of Contents

Introduction

Understanding the difference between pure and impure functions is important in functional programming, where the emphasis is on writing code that is easy to reason about and test.

The main differences between pure and impure functions are:

  1. Pure functions take objects or primitive data types as arguments but do not modify the objects. They don’t have side effects.
  2. Impure functions change the state of received objects.

Pure functions

A pure function is a function that has no side effects and always returns the same output for the same input parameters. In other words, a pure function is completely deterministic and does not modify any external state.

Functions are not called pure when they change in state internally or externally. Following are some examples of impure functions:

Add numbers

The following example snippet calculates the sum of two inputs and returns the output. If the inputs are the same for both values, then the output is always the same.

class Sum {
  public static void main(String[] args) {
    int sum = addNumbers(10, 9);
    System.out.println(sum);
  }

  public static int addNumbers(int first, int second) {
    return first + second;
  }
}

No matter how often we run the above method/function with the same inputs, we get the same output.

Test Cases: The following couple of test cases explain these functions' functionality.

  1. If we give 10 and 9 as input, we get 19 as output.
  2. For inputs 22 and 5, we get 27 as output always.

String manipulation

The String class provides functions to manipulate strings. Since these functions do not modify the input string and always return a new string based on the input parameters, they are pure functions.

public class StringManipulation {
  public static void main(String[] args) {
    String first = "Hello";
    String second = "World";
    String result = add(first, second);

    System.out.println(result);
  }

  public static String add(String s1, String s2) {
    return s1.concat(s2);
  }
}

Math functions

The Math class provides functions to perform mathematical operations. Since these functions always return the same output for the same input parameters and do not modify any internal state, they are pure functions.

public class MathFunctions {
  public static void main(String[] args) {
    int a = 2;
    int b = 3;
    double result = mathOperation(a, b);
    System.out.println(result);
  }

  public static double mathOperation(int a, int b) {
    return Math.pow(a, b);
  }
}

Immutable data structures

The java.util package provides immutable data structures such as List, Set, and Map. Since these data structures cannot be modified after creation, functions that operate on them are pure.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamOfIntegers {
  public static void main(String[] args) {
    List<Integer> input = new ArrayList<>(Arrays.asList(1, 2, 3));
    List<Integer> result = streamOperation(input);
    result.forEach(System.out::println);
  }

  public static List<Integer> streamOperation(List<Integer> input) {
    List<Integer> multiplyBy2 =
        input // collection of integers
            .stream() // Stream of integers
            .map(n -> n * 2)
            .collect(Collectors.toList());
    return multiplyBy2;
  }
}

Functional interfaces

Java 8 introduced functional interfaces such as Predicate, Function, and Supplier that represent pure functions. Since these interfaces only take input parameters and return output based on those parameters, they are pure functions.

import java.util.function.Predicate;

public class FunctionalInterfaceEx {
  public static void main(String[] args) {
    int A = 4;
    boolean result = isEven(A);
    System.out.println(result);
  }

  public static boolean isEven(int A) {
    Predicate<Integer> isEven = n -> n % 2 == 0;
    return isEven.test(A);
  }
}

Generally, any function that only depends on its input parameters and does not modify any external state is pure.

Impure functions

An impure function is a function that can have side effects or whose return value depends on some state other than its input parameters.

  • Impure functions can modify the program's state or depend on some external state, making them less predictable and potentially harder to reason.
  • Impure function mutates the state.

In most applications, an object's data is changed using a setter injection. This happens in an application with massive variables and objects constantly talking to each other, and at some point, the object reaches a state where it's hard to define the state of that object.

Following are some examples of impure functions:

Random number generator

The Math.random() function generates a random number between 0.0 and 1.0. Since the value returned by this function depends on the internal state of the random number generator, it is an impure function.

public class RandomNumber {
  public static void main(String[] args) {

    System.out.println(generateRandomNumber());
  }

  public static double generateRandomNumber() {
    return Math.random();
  }
}

Date/time functions

The java.util.Date and java.time.LocalDateTime classes provide functions to get the current date and time.

Since the value returned by these functions depends on the current system time, they are impure.

import java.time.LocalDateTime;
import java.util.Date;

public class DateTimeFunctions {
  public static void main(String[] args) {
    printDateTime();
  }

  public static void printDateTime() {
    Date currentDate = new Date();
    LocalDateTime currentDateTime = LocalDateTime.now();
    System.out.println("Current date is: " + currentDate + ", and time is: " + currentDateTime);
  }
}

File I/O operations

The java.io package provides functions to read and write files. Since these functions can modify the contents of a file or create a new file, they are impure functions.

import java.io.FileWriter;
import java.io.IOException;

public class FileIOFunctions {
  public static void main(String[] args)throws IOException {
    fileIOOperations();
  }

  public static void fileIOOperations()throws IOException {
    FileWriter writer = new FileWriter("example.txt");
    writer.write("Hello, world!");
    writer.close();
  }
}

Network I/O functions

The java.net package provides functions to communicate with servers over a network. Since these functions can modify the state of a network connection or receive data from a server, they are impure functions.

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class NetworkIOFunctions {
  public static void main(String[] args)throws IOException {
    networkOperations();
  }

  public static void networkOperations() throws IOException {
    Socket socket = new Socket("www.example.com", 80);
    InputStream in = socket.getInputStream();
    byte[] data = new byte[1024];
    int bytesRead = in.read(data);
    socket.close();
  }
}

Generally, any function that modifies the program's state or depends on some external state is impure.

Impure functions can make code harder to understand and test, as their behavior can be affected by the external state that is not controlled by the function. While impure functions can be useful in some situations, they should be used sparingly and cautiously.

Java Streams APIJava

Gopi Gorantala Twitter

Gopi is an engineering leader with 12+ of experience in full-stack development—a specialist in Java technology stack. He worked for multiple startups, the European govt, and FAANG in India and Europe.

Comments


Related Posts

Members Public

Differences Between JDK, JRE, and JVM?

Short answer JDK, JRE, and JVM are essential components of the Java platform, each serving a distinct purpose. Here are the key differences between them: 1. JDK (Java Development Kit): The JDK is used by developers to write, compile, and debug Java code. 2. JRE (Java Runtime Environment): End-users use

Members Public

Difference Between String and char[] in Java

Short answer Strings String is an object with many helpful methods. String class in Java's standard library is designed to handle text as a sequence of characters. A string of characters (string object) is non-modifiable or immutable in Java. Once you've created it, you cannot modify

Members Public

What is an Object class in Java?

Short answer Object class is the super class of every class you can create. In Java, a class extends another class using the keyword extends. If you don't have any other class to extend, that's fine. The compiler will make your class extend the Object class.