Functional programming in PHP - anonymous functions, closures and tail calls

By Steve Claridge on 2014-03-15.

This post gives a brief introduction to functional programming with PHP. It doesn't dive into the details of functional programming but it does try and show how the functional style differs from the common imperative style of coding.Reading the Wikipedia entry for imperative programming should give you a good primer on the fundamental difference between how most of use code every day using PHP and functional programming.

Below is a very simple loop for reading a file and printing its contents in PHP:

$f = fopen( "robots.txt~", "r" );
while ( ( $l = fgets( $f ) ) != null )
{
    echo $l;
};
fclose( $f );

Now the same thing but in a functional style:

function readLines( $filename )
{
    $f = fopen( $filename, "r" );     return function() use ($f)
    {
        $l = fgets( $f );
        if ( $l == null )
        {
            fclose( $f );
        }
        return $l;
    };
}; $line = readLines( "robots.txt~" );
while ( ( $l = $line() ) != null )
{
    echo $l;
};

Yes, it's more lines of code to do the same thing, get over it, it's just an example for illustration. Lets step through the functional PHP snippet:

We create a function called readLines() , notice that this function returns a function! readLines() opens the given filename and stores the file-handle in the $f variable, the next line is important, forget the return statement and we are left with this

function() use ($f)

We are creating a closure here, readLines() defined the $f variable and then returned immediately, ending the function, which would normally mean that $f goes out of scope and is garbage-collected. But not in this case, notice that $f is the parameter to the function defined in the return statement; we are telling PHP that the result of this function is a function and that the $f variable must be available for the lifetime of the returned function.

The returned function is an anonymous function, and a closure is a type of anonymous function where one or more variables are "bound" to the function; in other words the variable(s) stay in scope for the lifetime of the anonymous function.

The operation of the anonymous function itself is fairy straightforward, it reads the next line from the file $f , if its the end of the file it close the file, and it returns the line $l . So each time we call this function it returns the next line from the file.

Now, the entry point of the code:

$line = readLines( "robots.txt~" );
while ( ( $l = $line() ) != null )
{
    echo $l;
};

This calls readLines() with the file to be read. Remember here that readLines() returns an anonymous function, so $line is a function. Finally, the while loop keeps calling the $line function until the file has been completely read.

This simple example shows the anonymous function syntax in PHP and how a closure is created by passing a variable to it. The functional example can be improved, the while loop at the bottom of the example should be replaced by a recursive function, more on recursive functions in a later post.