PHP 5.3 packaged the power of functional programming by adding support for lambda functions and closures. You will be familiar with them in javascript. In this article we will have a look into these features and its usages.
Lambda functions
Lambdas (Anonymous functions), simply saying, are functions without a name. Anonymous functions are not new to php. We were able to write them from php4 onwards using create_function() function.
The problem here is body of our function will be a long quoted string which will be hard to manage and we will need to escape any quotes inside it. The same thing we will write as a lambda function as follows
I have said lambda functions won’t have a name and yet we gave a name to the function?. Remember it’s not a name of that function but just a reference to that function. Often we will be using lambdas as callback functions to other functions and there we won’t be giving any name. Though this simple example can’t explain any advantage of anonymous function, there are some situations where we can utilize them efficiently to simplify the code. I will come to that later.
Closures
In practice closures are little more than lambdas. A closure is similar to an anonymous function which can attach a variable to it by using the ‘use’ keyword. Theoretically speaking a closure is a function that wraps the current scope and can have one or more variables attached to it.In order to understand closures you should have a clear idea on scope of a variable in PHP. Since the notion of scope in PHP id little bit different from other languages, this is not so straight forward. Lets take a look in to a javasctipt function that will return the factorial of any given number.
Now let’s language cast this code to php.
Oops.. It’s not working. Why? Here comes the difference of scope in PHP with other programming languages. In javascript we can simply call the anonymous function from inside them, which is not allowed in php. (Also we can’t use FUNCTION to access it, because it’s a closure not a function..!!). Oftentimes we will need to access variables from the current (outer) scope inside the closure. Also it may not be able to pass them as a parameter. Here we will make use of ‘use’ keyword to inform that we need to use these variables inside the closure. Now lets have another example which will demonstrates this, before going to the closure version of our factorial function.
Everything will be almost clear from the above example. Using this great math class we can set a multiplier during instantiation and find its product with any number. Note that inside the closure we have assigned $this to $self, because closures don’t support $this variable. In PHP closures are internally managed by a closure class. Closures are an object of closure class. When we call them we are actually invoking an object as if it is a function. PHP 5.3 introduced a new functionality, ‘__invoke()’ method which enabled us to call an object as a function. If $this variable is allowed inside the closure, it will be applied in the context of closure object itself.
Lambdas are a special case of closure and lambda functions created this way are also returning an object of type closure, even though they don’t make use of any property of closures.
Difference between closure and other objects in PHP is, if an object is data and methods that applied on that data, closure is a function with data bound with that function.
Getting Deeper
Closures are extremely useful when programming in event driven environment for implementing callback functions. They make implementation very simple by implicitly binding the calling environment with the function. Imagine how it will be if JavaScript don’t support anonymous functions. We may need a function reference to be passed wherever a callback is required. In PHP, though we may not be able to make use of closures as in other languages, there are certain situations where we can efficiently use them for simplifying the code. I will mentions some examples below.
Application prototyping
We can use closures for prototyping our application. By defining a simple class and dynamically creating the functions we needed we can demonstrate the functionality of the system. For Example
Here we have created a method for that class on the fly. Like that we can create any number of functions, just to demonstrate the functionality.
Implementing callback functions
Another use of closure is in implementing callback functions. Consider an array function ‘array_filter()’ which will take two parameters, first one is the array and second argument is a callback function which will be called against each element in that array. Here we will write the callback function itself as the second argument.
This can be used in implementing modular system with least coupling between the components. There also we may need to implement some callback functions whenever a particular event occurs. (Think about hooks in drupal or actions and filters in wordpress, which will be called on occurring particular events).
Factorial function using lambda function
For finding the factorial of a number using lambda function we will make use of a Y-combinator which is a brain twisting function that will convert any non recursive function to a recursive one. It is written by Stanislav Malyshev in his article Y-Combinator in PHP. It is interesting that Y-combinator has a strong relation with lambda calculus.
The closure way of same factorial function is given below, which is well simplified.
Eli White, in his article, ‘An intriguing use of lambda functions’ describes a specific use of closures.
Additional notes
Since closures are anonymous, they do not appear in reflection. However, a new method was added to the ReflectionMethod and ReflectionFunction classes: getClosure. This method returns a dynamically created closure for the specified function. We can check if a function is closure or not by using isClosure method. For more about this please refer Here.
For an introduction to Reflection api You can refer my previous article
Php version 5.3.4 has fixed some bugs related to closures
Converting closure to array yields empty array
Memory leak when passing a closure to method_exists()
ReflectionClass fails on Closure class
Conclusion
Sometimes we will need to write a function which will be used only once. Lambda functions allow the quick definition of such throw away functions.Even though closures dont bring any thing new to PHP they can help us in managing our code by simplifying it. In future we can expect a new, different programming style in PHP which will make use of this closures and lambda functions extensively.
References
http://en.wikipedia.org/wiki/Anonymous_function
http://php.net/manual/en/function.create-function.php
On PHP 5.3, Lambda Functions, and Closures
http://www.ibm.com/developerworks/opensource/library/os-php-5.3new2/
Expert PHP and MySQL