What are Closures and Lambdas in PHP?

What are Closures and Lambdas in PHP?

images
Closures and Lambdas were added into PHP in `5.3` release. Since then we all are using them knowingly or unknowingly in our day-to-day PHP programming.
Have you ever wonder how it works when you pass a function as a callback to `array_map` or `array_walk`. They are all Lambdas and Closures sometimes depending upon your implementation.

So In this post we will talk about the Modern PHP language features like Lambdas, Anonymous and Closure functions briefly.

What is Anonymous function?

As per PHP documentation, Anonymous functions, also known as closures, allow the creation of functions which have no specified name. They are most useful as the value of callback parameters, but they have many other uses. So in a nutshell, An Anonymous function is a function without name. If you are familiar with `JavaScript` then you might already have used Anonymous functions.

For example, a regular function in PHP will something look like this:

// Regular function with name
function greet () {
    return "Hey There!!";
}

And then we can simply call this function like:

echo greet ();
// It will echo "Hey There!!"

Now the Anonymous function having the same functionality as above will look like this:

// Anonymous Function
function () {
    return "Hey There!!";
}

But how do we call it, It doesn’t have any name?
So Anonymous functions can not be called like the regular functions instead they can be called via assigning them to a variable or passing them as a callback or argument to another regular function.

For example,

// Assign Anonymous Function
// to a variable
$greet = function () {
    return "Hey There!!";
};

// Now we can call the Anonymous function
// it will echo "Hey There!!"
echo $greet();

So `$greet` here points to a Lambda Function.

What is Lambda?

So a Lambda is an Anonymous function that can be assigned to a variable or can be passed as an argument or callback to another regular function.
Let see how can we pass an Anonymous function as an argument.

// Passing a Lambda to a function 
// Notice, Here $message is a function and we are passing it as an argument
function greetUser($message) {
    echo $message();
}

// Now Try to call the greetUser Function
greetUser(function() {
    return "Hey There!!";
});

Another interesting example of Lambda would be passing a `callback` to `array_map` like this:

// Say, we want to calculate the Cubes of the Given array of Numbers
$numbers = array(1, 2, 3, 4, 5);

// We can use array_map with a Lambda that runs over every element of the array mentioned above
// and calculates the cube.
$cubes = array_map(function ($n) {
    // Calculates the Cube
    return($n * $n * $n);
}, $numbers);

print_r($cubes);

// This will output like this:
Array
(
    [0] => 1
    [1] => 8
    [2] => 27
    [3] => 64
    [4] => 125
)

Why Should I use Lambda?

Now we have seen that Lambdas are quite handy functions that we can create without being worried about its concrete class and location. They are like use and throw functions that we might need just to get job done once. They, most of the time do not fit in to the Global Space and required only once to do the job. Like the Lambda to calculate cube above or Lambda to greet user required only for that particular job, So it doesn’t make sense to Put them in to some class and let them be the part of code that rarely be used again.

So we have seen that What is Lambdas, Anonymous functions and why and how do we use them. Now lets see What is Closures?

What is Closure?

Closures are same as Lambdas except that they can access variable from the Parent Scope. And any such variables must be passed to Closure by using the `use` language construct of PHP.

For example:

// Declare a user name
$user = 'Codezuzu';

// Create a closure by passing the variable 
$greet = function () use ($user) {
    return "Hey There!! $user";
};

// Now call the closure
// It will be able to access the $user variable inside the Function
echo $greet();
// It will output Hey There!! Codezuzu

So we can see that Closure can use variables from the Parent Scope or Scope outside of itself. Like in the example above $user is accessible inside the closure by means of `use` construct.

Any changes made to the variables passed to closures inside closure will not reflect in Global Scope or will not change the original variable unless we pass that variable by reference using `&`.

Let see:

// Declare a user name
$user = 'Codezuzu';

// Create a closure by passing the variable 
// Note: we are passing the variable as a reference
$closure = function () use (&$user) {
    $user .= " is beautiful";
    return $user;
};

// Now call the closure
echo $closure();
// It will output Codezuzu is beautiful

// But now the value of $user variable has also been changed, as It was passed as reference and been modified in closure
echo $user;
// This will also echo Codezuzu is beautiful

Another Example:

// Create a counter
$counter = 0;

// Create a Closure
$increment = function () use ($counter) {
    $counter++;
};

// Call Clouser
$increment();

// Try printing $counter
echo $counter; 
// It will still echo 0 Although we have increased it inside Clouser because 
// the variable was passed as a value not by reference

// Now lets pass it as reference

$increment = function () use (&$counter) {
    $counter++;
};

// Call Closure
$increment();
$increment();

// Now we have Incremented the counter twice, So it should be at 2
echo $counter;
// It will output 2

So we can say Closures comes very handy when we need to access or update the variables from Parent Scope with functionality of a Lambda.
We can pass as many variables as we want to Closures in `use` separated by comma `,`.

Another real life example of Clouser:

// Say You have a class where you accepts an array of arguments from the Constructor like this

class MyClass
{
    /**
     * Class Constructor
     * @param array $args
     */
    public function __construct(array $args)
    {
        // Handle args here
    }
}

// Now You want to get the Values out of the $args for the given Keys. They might exist or not, So you need to 
// handle that case as well. we can simple do $args[$key] as this can throw Undefined Index Exception if key doesn't exists
// in the $args variable. 
//
// Since creation of a Class is controlled by external interfaces, So we can't be sure what comes to $args. We can only try
// to get out values required for our class.
//
// We can use a clouser here to help us

class MyClass
{
    /**
     * Class Constructor
     * @param array $args
     */
    public function __construct(array $args)
    {
        // Create a closure function $get to extract the variable
        $get = function ($key, $default) use ($args) {
            return (array_key_exists($key, $args) === true)
                ? $args[$key]
                : $default;
        };

        // Now we can easily ask for a key like this
        // It will try to get the value from $args, If it doesn't exists then It will return the default
        $property1 = $get('property1', 'myPropertyOne');
        $property2 = $get('property2', 'myPropertyTwoDefaultValue');
    }
}

Although, we can argue that above mentioned method $get is not the idle way to extract the variables and we can use some other better technique for that. But this is just an example to understand the Closure. possibilities are endless. In the similar fashion we can use clousers to get values from `$_POST` or `$_GET` or from any variable. We can also use them in PHP functions like array_walk, array_map, array_filter etc. They have proved very handy in that cases.

Summary

So we have just saw the Lambdas, Anonymous function and Closures in PHP. I hope you like reading it.
Nowdays, almost every programming language supports Closures and Lambdas. In fact, languages like Javascript, Scala are using Closures very heavily. Almost all of the modern PHP frameworks use closures for there Rounting and Controller needs. For example in Silex, Slim, Laravel you can match a route to a clouser. And that clouser will actually works like your controller.

As I said, Possibilities are endless, It’s solely depends on us how do we see things and how can we use them in programming.
Please let me know your thoughts or any suggestion in comment box below. We will come with another useful post soon. Till than Happy Coding !!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.