The state of functional programming in PHP
With the rise of Javascript, and languages like Python and Ruby, functional programming is becoming more mainstream. Even Java seems to be getting closures in the next version, so does this leave PHP lacking behind or is there an unrealised potential hidden within?
Dynamic dispatch
What exactly defines a functional programming language, is perhaps an open question, but one key element is functions as data. As it happens, PHP kind-of-supports this concept; The syntax permits you to use variables as function-names, making the following possible:
function add($a, $b) {
return $a + $b;
}
$add = "add";
$add(2, 8); // return 10
Unlike languages with first class functions support, the variable $add
isn’t a special type — It’s merely a string, which is evaluated in the context. It may just be a wrapped up eval, but superficially it works similar, once the function has been declared.
It is also possible to explicitly call a function reference with call_user_func. This is interesting, because it accepts different types of arguments, which makes it possible to call a method on an object. More on this in a moment.
Binding state
Another prerequisite for functional programming, is the ability to bind a variable to a function. This bound function serves essentially the same purpose as objects do in object oriented programming, but is usually more fine grained and more flexible.
In languages, which are traditionally associated with functional programming, functions are usually bound with variables, through something called a closure. This is a side effect of the scoping rules of those languages.
Since PHP doesn’t have lexical scope, we can’t use closures, but we can use currying to achieve the same goal. In Wikipedia’s words, currying is the technique of transforming a function that takes multiple arguments into a function that takes a single argument. If that sounds abstract, assume the following:
$add2 = curry($add, 2); // returns a new function reference, to add(), bound with 2 as the first argument
$add2(8); // return 10
Before you try that out, hold your horses — it won’t work, because curry
isn’t a PHP function. As it turns out though, it’s possible to create it. Sort of.
Implementing curry
Without going into great details, there are two ways, currying can be implemented in PHP.
- The first option is some sort of run-time evaluated code. This could be variable-variables, pointing to function names or callback pseudotype, invoked by call_user_func. Eventually, they are just kinds of eval.
- The other option is to use a command object, encapsulating the callback and its state.
For a more detailed explanation, have a look at Partial function application in PHP.
Weighing the options
Looking at the syntax, variable-variables have a much more functional “feel” to them, than a command object. The callback pseudotype does allow one to reference an object + method-name, but even though this is supported by PHP’s internal functions, it get’s bulky in user land code. If a command object feels like functional programming with OOP syntax, then call_user_func
feels like functional programming with procedural syntax.
When it comes to performance, the run-time evaluated approach has some serious shortcomings. Currying must be done by creating new static code each time and this can’t be reclaimed until the end of the process. Furthermore, the only way to bind state, using this pattern, is to rely on a global container of some sort, generating a new, unique symbol each time. Since it’s impossible to know, when the callback isn’t referred anymore, it follows, that it’s impossible to safely remove the variable from the global container. Thus, any state bound this way, will be impossible to reclaim for PHP’s memory management system, furthering the risk of the script running out of memory.
In conclusion
So, if the offset for this post was to assert the current options for functional programming in PHP, the only practical solution is currying, using command objects. The awkwardness can be somewhat smoothed out, with a library of utility classes. phunctional is an attempt at this and we might also see some of these ideas emerge into more general purpose frameworks.
Another idea, could be a language level addition to PHP. What we need, is a way to make all callbacks callable with the variable-variable syntax. I’m thinking this could be supported with a magic-method. If an object was to be used as a function, and it implemented said magic method, the method would be called. From a design perspective, it would fit fine with the other magic methods, such as __call
and friends.
Declaring functions
Another limitation, which could be addressed at the language level, is the matter of declaring functions in the first place. Currently, functions must be declared in the global scope or through the use of the hideous create_function. There have been some stabs at improving this, on the php-internals team, so maybe we should be as lucky as to see this in PHP 6?