Lambda functions and closures in PHP 5.3

Introduction

With PHP 5.3 a lot of new features have found their way into the language. But are they really new? Actually some of these features are quite old. Lambda functions for example originate from the lambda calculus which was introduced by Alonzo Church and Stephen Cole Kleene in the 1930s. In the lambda calculus, functions are first-class entities: they are passed as arguments, and returned as results.

Lambda functions are implemented in many modern programming languages like C#, JavaScript, Python, C++ and many more..

The concept of closures is also quite old. It was developed in the 1960s and was first fully implemented as a language feature in Scheme. Let's take a look at those features and see how useful they can be.

Lambda functions

To start let's take a look at the following code:

Listing 1: <?php $square = function($x) { return $x*$x; }; print $square(2); ?> Result of listing 1: 4 In the above you see a function assigned to a variable. Doing this in PHP isn't really new. It was possible through ' create_function' from the early versions of PHP 4.

New is the syntax to create and use these anonymous functions. They can now be used in places where you previously had to hand over a function name as a string (or in short: callbacks). The function array_map takes such a callback to map each element of an array to that function.

Listing 2: <?php print_r( array_map( function ($n) { return $n*$n; }, array(1,2,3,4,5) ) ); ?> Result of listing 2: Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 )

Instead of defining a function in the global namespace and handing it's name over to array_map, we define an anonymous function in the call of array_map. The advantage of this approach is clear: The function only exists temporarily and does not pollute the global namespace. As of PHP 5.3 you could of course use a namespace to hold such functions, but it's not really useful to do that with a function or only use once or twice.

The abstract syntax for an anonymous function is as follows:

function & (parameters) use (lexical vars) { body };

Closures

A closure is a first-class-function with free variables. Closures are defined within the scope of their free variables, and the extent of these variables is at least as long as the lifetime of the closure itself. Let's take a look at a basic example:

Listing 4: <?php $config = array( 'database' => array( 'host' => 'localhost', 'user' => 'peter' ), 'paths' => array( 'images' => 'images/', 'styles' => 'css/' ) ); $getConfigType = function($type) use ($config) { if(array_key_exists($type, $config)) return $config[$type]; else return false; }; $pathConfig = $getConfigType("paths"); var_dump($pathConfig);

Result of listing 4: Array ( [images] => images/ [styles] => css/ )

Because closures look quite similar to lambda functions they are often mistakenly called "anonymous functions". The concepts behind lambda functions and closures are, however, distinct concepts.

Now to the above listing: The new keyword "use" is what makes this anonymous function a closure. The variable $config which is defined outsite the function's scope is generally not accessible inside the function. With the "use" keyword however, the variable gets bound to the scope of the function.

This bond between the function and the variable is always there! Even if I use $getConfigType as a parameter for a method on an object and it gets invoked inside the object, the reference to the initial variable is still there.

The magic __invoke

Coming soon.

Comments (0) |

No comments yet!

Submit Comment