Functional Programming in PHP: Part 2

Lochemem Bruno Michael
4 min readSep 15, 2017

--

I love to liken my experience with learning and embracing a new paradigm, in this case, functional programming to familiarizing oneself with the dynamics of a brilliant niche television show. Getting to understand the dynamics of the relationships that exist in the show’s universe, as well as the nuances in the niche of the show, are all quite challenging yet rewarding. Bland analogy? I hope not. I certainly do not intend to bore you, the reader with allegories with little or no impact on the gist of the matter, function purity.

Understanding function purity is pretty difficult to grasp. As is the case most learning experiences, familiarizing oneself with the underlying concept of purity involves following a logical learning sequence. First, one needs to comprehend the definition of a pure function. Simply put, a pure function is one with neither side-effects nor side causes. Side-effects and side-causes are endemic to imperative programming, a programming pattern driven by the execution of statements that change a program’s state.

session_start();$fName = "Michael"; //assign to the variable the value Michael$_SESSION['username'] = $fName . "Bruno"; //create a session variable

By assigning to the session variable username a concatenated string, I have triggered a state change. A function whose return value is one modified outside of its scope is considered impure. The implication is that all functions whose return values are contingent on the return values of functions like date() and random() as well as those dependent on global variables and file interactions are impure. That is the important second part to the comprehension of pure functions.

$counter = 0;function inc() {
global $counter;
return $counter++; //the global variable renders this impure
}
function timeAdvance() {
return time() + 5; //returns a new value every time it is run
}
function dbUpdate($orm, $value) {
return $orm->instantiate()
->update('some query', $value)
->execute();
} //interacts with a database and is impure

The previous assertion brings me to the final axiom of pure functions — they always return the same output given the same input. This deduction is one derived straight from Category Theory, the basis for functional programming (I will explore this in detail later). Anything resembling the examples below should suffice as a proof of concept.

function add(int $a, int $b) : int
{
return $a + $b; //should return a sum of $a and $b
}
function wait(int $returnValue) : int
{
sleep(10);
return $returnValue; //simple lazy evaluation
}

Referential transparency is next on the agenda because one can only say so much about pure functions without mentioning the substitutability of expressions. Referential transparency is a concept defined as the ability of an expression, in this case, a function, to be replaced by its output without changing application behavior. Implicit in this definition are immutability, a concept I discussed in a previous article and function purity.

Immutability is important because not only does it reduce the cognitive burden when it comes to reasoning about code but also minimizes synchronization errors which might result from multiple, inconsistent state changes. PHP has support for constants which sadly, can only be bound to scalar values. Immutable objects, the topic of one of my previous posts, cannot be organically created, however, immutable arrays, strings, integers, floating point numbers, and characters can.

const USERNAME = 'Michael';const USER_PREFERENCES = [
'favBasketballTeam' => 'Miami Heat',
'favMovieFranchise' => 'Star Wars'
];
const FOUR_FACTORIAL = 24; //integerconst PI = 3.14159;

Referentially transparent functions are pure functions with immutable data structures. The following example demonstrates this concept.

class BasketballGame {

public $home;

public $away;
public function __construct(int $home, int $away) {
$this->home = $home;
$this->away = $away;
}
}
const TWO_POINT_SCORE = 2;const THREE_POINT_SCORE = 3;function twoPointerHome(BasketballGame $game) : BasketballGame
{
return new BasketballGame(
$game->home + TWO_POINT_SCORE, //you could simply use 2
$game->away
);
}
function threePointerAway(BasketballGame $game) : BasketballGame
{
return new BasketballGame(
$game->home,
$game->away + 3 //you can use THREE_POINT_SCORE
);
}
$gswSas = new BasketballGame(0, 0);$gswSasQone = twoPointerHome($gswSas);
//should output a home score of 2 and away score of zero

The functions twoPointerHome() and threePointerAway() are pure, the constants TWO_POINT_SCORE and THREE_POINT_SCORE immutable and the value $gswSasQone referentially transparent. This is so because one can simply replace the twoPointerHome() function result with a new BasketballGame object instantiated with values 0 and 2.

$gswSasQone = new BasketBallGame(2, 0);

In conclusion, side-effects, side-causes and all the concepts central to referential transparency can be quite difficult to get one’s head around. Practice can flatten the steep learning curve. The next exposition will feature value objects, helpers and my brand new bingo-functional library.

The series — Functional Programming in PHP — is now a book. The volume eponymous with the blog content is currently available on Leanpub.

--

--