Overview: Potentially-pure functions are argument-based higher-order functions (i.e., functions that accept other functions as arguments) with pure function bodies (i.e., function bodies that are consistent and side-effect free), meaning their purity is dependent upon the arguments passed into the function.
All potentially-pure functions are higher-order functions, so let’s begin with a brief overview of what it means to be a higher-order function.
Higher-order functions accept functions as arguments (we’ll call this specific form argument-based higher-order functions) or return functions as values (we’ll call this specific form return-based higher-order functions.) Higher-order functions enable tremendous power, flexibility, and parsimony; and they are leveraged heavily in functional programming.
In order to implement argument-based higher-order functions, a programming language must allow you pass functionality into functions through their arguments. While not all languages provide first-class functions, which can be passed around and stored like other data, you can effectively emulate first-class functions in most languages. In low-level languages like C, you can pass in function pointers; in OOP languages like Java, you can pass in interfaces; and in dynamic languages like PHP which used to lack anonymous functions (prior to version 5.2), you can pass in the string name of an existing function. No matter what language you’re using for your development, you should be able to fake it quite convincingly.
Pure functions are side-effect free and consistent. Higher-order functions provide a special situation when evaluating purity. If an argument-based higher-order function’s body is pure, then its purity is unfixed. In other words, the purity of the function is dependent upon the purity of the functions passed in as arguments. If the functions passed into the higher-order function are pure, then the function is pure; and if the functions passed in are impure, then the higher-order function is impure*. Because the phrase “argument-based higher-order function with unfixed purity” might jeopardize your conscious state, let’s just call this function type a potentially-pure function.
The natural duality of potentially-pure functions makes them especially helpful when it comes to isolating side effects. When testing a potentially-pure function, a pure form of the function can be passed in, allowing you to cleanly and easily test all possible states. When using a potentially-pure function in production, a fall-through function containing the side effect(s) can be passed in, allowing the code to perform its real-world requirements.
* If an impure function is passed to an argument-based higher-order function with unfixed purity, it is possible for the function to remain pure if the impure function passed in as an argument is never called.