Functional programming techniques in PHP
Functional programming has gained a lot of traction those 3 to 5 last years. First, there are some success stories around it : Twitter move to Scala, Whatsapp being written in Erlang. Then we have some new kick-ass languages like Rust. Finally, it seems the new hype is to create a functional language compiling to javascript : Elm, Purescript. On a more academic front, there is also research on new concepts like dependant typing, see Idris for example.
Those are all cool and shiny new toys, but we can benefit from some techniques without having to learn a new tool, just by applying some principles to our everyday PHP! But first of all, what exactly is functional programing?
Functional programming
Functional programming is a paradigm as are imperative, logical and OO programming. The main point is that everything is a function, in the mathematical sense. The corollary of that is that you cannot have side effects since all outputs depends solely on the input of the function. It also means you cannot have any mutable state, once
something was computed, it cannot be changed to something else.
This can be cumbersome a time, so a distinction was made between pure functional languages (like Haskel or Ocaml) and other function languages, Scala for example, where you can introduce mutable variables or even do plain old Java.
Another issue are input and outputs which are by definition mutable, the "problem" has been resolved in most functional languages by wrapping them into a Monad, the rest of this blog post will not talk about that, so I won't explain this barbaric word, but feel free to do some research on the internet, it is really interesting.
Despite all those lengthy explanation, functional programming is first and for all a way of thinking and solving issues than can be used in any languages. It is just easier to do in some that are designed for it.
The advantages
Since the output depends solely on the input, reasoning about a function is made a whole lot easier, you have everything under the eyes, there is no need to keep in mind any kind of global or shared state, thus reducing complexity a lot.
Testing is made easier, you don't have to mock a lot of dependencies or create big ass objects, you just need to pass the arguments your function need.
A functional style also often result in writing small and self-contained functions used later as building blocks for bigger functionality, resulting in clearly decoupled code and extended reusability.
A nice little bonus of a pure function is that you can cache its result, this is called memoization but more about that later.
A perhaps less appealing argument for us, is that calls to pure function can easily be distributed across threads or even computers because you have the guarantee that the inputs are enough to perform the computation and that there will be no side effects. It is simply a matter of combining the results again at the end.
The basics
The first important thing is that functions are, more or less, first class citizen in the PHP world :
// Function as a variable
$func = function() {
return 42;
};
// Function as a return type
function createFunction() {
return function() { return "Thanks for all the fish"; };
};
$func2 = createFunction();
// Function as a parameter
function display($func) {
echo $func()."\n\n";
}
// Call a function by name
call_user_func_array('strtoupper', $someString);
// objects as functions
class SomeClass {
public function __invoke($param1, $param2) {
[...]
}
}
$instance = new SomeClass();
$instance('First', 'Second'); // call the __invoke() method
Knowing that, we can start playing around with basic functional concepts. For each example, the "common" way of doing things will be presented first followed by the functional one. As it is often the case in functional programming, we will most of the time manipulate an array.
Applying a function to all elements :
// The imperative way :
foreach($stringArray as $k => $v) {
$stringArray[$k] = strtoupper($v);
}
// The functional way :
$result = array_map('strtoupper', $stringArray);
"Reduce" an array, often called "fold" in functional languages :
// The imperative way :
$result = 0;
foreach($int
Truncated by Planet PHP, read more at the original (another 7158 bytes)
Link