Many have at least heard about Functional Programming, but use PHP for work. While I encourage everyone to try something like Haskell I’m going to try and do some Functional Programming in PHP
What is Functional Programming
An excerpt from wiki:
functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state
If I were to define it in my own words I would do it by comparing the imperative approach to programming with the functional one. In the first case you reason about solving a problem step by step, like this:
Imperative “getting into the house” solution:
get the keys out of the pocket
pick the right key
open the door with the key
enter the house
Functional “getting into the house” solution:
enter the house
through the door opened
with the right key
chosen from all the keys you get out of the pocket
The PHP code
Read the comments:
There is some “state” in which our house, door and the pocket are. We change this state in order to achieve our goal. Step by step.
Some people might say it is bad to use globals. It is, that’s just to illustrate the approach. Most of “object-oriented” PHP projects still utilize the state heavily: singletons, statics, “registry pattern”. Globals even.
Some people might object that they actually never use any of those and only do Dependency Injection and use new frameworks like Symfony 2. Well, you already using functional programming to some degree! Dependency Injection (or parametrization) is a step in that direction. I personally think that “Object Oriented Programming” when done correctly is closer to functional style than imperative or procedural.
While there are a few languages that are “paradigm specific”, functional techniques are slowly getting soaked into many of them, including PHP.
Problem solving with Functional Programming
We start with “entering the house”. That is, without knowing what we’ll have to do to actually enter it. That highlights the ease of prototyping. In imperative programming you have to think trough all the steps and make sure they will get you where you need to be. In functional programming: you know where you need to be and you try to express what needs to be done for that.
“Functional” is the way you reason about solving a problem. In order to use functional programming you don’t necessary need special tools - you just need to think right. However if a language lacks particular features it may be not worth it to use it for Functional Programming. Let’s review some of the characteristics and features that “make a language a functional one” and what we can do with PHP.
Pure functions, immutable data
Pure functions are those that have no side-effects and for any given set of parameters always return the same result. In languages like Haskell all functions are pure whether you want it or not, in PHP it’s not the case.
What I suggest for PHP developers is to make functions pure when possible. Try to isolate impure stuff (where bugs tend to happen). For that, you need to follow these two leads:
avoid state
avoid mutable data
By “application or system state”, we mostly refer to Input/Output operations, working with data storages and external services. Try to separate application logic from everything state-related whenever possible.
There is not much you can do to avoid mutability in PHP. Simply make sure your pure functions are pure when treated as a “black box”.
Here is an excercise: when you create a function, type “return” the next line. This way you:
don’t have much place to create mutable data
are forced to introduce new functions to keep the code sane
For instance, you could have that enter_house function coded like this:
While the function still does the same, you create temporary variables when can be avoided and may omit introducing functions thus spoiling decomposition. If you need temporary variables, consider “values binding”:
Some mutable data here, but looks and feels like immutable. This is nothing more than a fun trick to start thinking in the right direction. When needed, all the PHP power should be made use of.
First-class functions and Higher Order functions
Wikipedia says that PHP does have First-class functions since the 5.3 version with the exception of partial application and nested functions. They refer to the Closures added. However due to dynamic nature of PHP you could use other types as if they were functions, even before PHP5.3:
There is this pseudo-type: “callable” and as of PHP5.4 you are able type hint on it. (https://wiki.php.net/rfc/callable). In prior versions you need to know that callable may be a string, an array or a closure. You can pass/return strings, arrays and closures to/from functions, which gives us the higher order functions:
Closures and anonymous functions
Anonymous functions are those without a name. We have them as Closures since PHP5.3 (and before that we could create anonymous functions via create_function). Usually useful for some things small when it’s really not worth it to create a real function:
Closures are a much more powerful toy through which you can simulate some of the functional programming languages features - I’ll show more on that later. For now, let’s say that we have closures in PHP and in order to create a reference to an outer scope variable you have to use the “use” keyword:
Recursion
Recursion in computer science is a method where solution to a problem depends on solutions to smaller instances of the same problem.
This is all for the sake of avoiding state and mutable data. Here is an example of pick_the_right_key function implementation for the case when we don’t know if it’s indexed by “housekey”. For instance it could be a situation when we don’t know the key’s color but we remember it has a tiny label on it and we need to check all keys in order to find it.
In case with the recursion code we don’t have consecutive instructions: we express our needs through calls of other functions. Even if it’s the same function.
Partial Application and Currying
Partial Application and Currying are actually different things. I’m going to speak about partial application: a way to get a new function by partially applying another one.
Let’s say there is a function like this:
at some point you realize that you need another one in a few places. One that does the same but the value of $a is fixed so you create something like this:
Normally, in PHP you could just create another function embracing a call to the original function. But if you get on well with the functional way of thinking you may need to dynamically create functions based on existing ones for your particular local needs.
I have a special curry function that makes it possible to create these functions on the fly. Here is the function and how you can use it:
Free-point style and functions composition
This is similar to currying from some point of view as it allows you to get a function for a particular local need that composes a few other functions without having to explicitly define it.
Here is what you would normally do in PHP:
Here is a function that does this on the fly and a usage example:
The idea here is that with closures many features of programming languages can be simulated.
Comments and feedback are much appreciated. See contact details here