Anonymous Functions in PHP

Anonymous functions, or lambda functions, are functions without a name. As they do not have a name, in order to be able to invoke them, we need to store them as variables. It might be strange at the beginning, but the idea is quite simple.

So let’s just add the code into init.php, and then remove it:
$addTaxes = function (array &$book, $index, $percentage) {
$book['price'] += round($percentage * $book['price'], 2);
};
This preceding anonymous function gets assigned to the variable $addTaxes. It expects three arguments: $book (an array as a reference), $index (not used), and $percentage. The function adds taxes to the price key of the book, rounded to 2 decimal places.

We could instantiate a list of books as an array, iterate them, and then call this function each time. An example could be as follows:

$books = [
['title' => '1984', 'price' => 8.15],
['title' => 'Don Quijote', 'price' => 12.00],
['title' => 'Odyssey', 'price' => 3.55]
];
foreach ($books as $index => $book) {
$addTaxes($book, $index, 0.16);
}
var_dump($books);

In order to use the function, we just invoke it as if $addTaxes contained the name of the function to be invoked.


Benefits

1. One possible application would be to use it as a callable. A callable is a variable type that identifies a function that PHP can call. We send this callable variable as an argument, and the function that receives it can invoke it. Take the PHP native function, array_walk. It gets an array, a callable, and some extra arguments.

PHP will iterate the array, and for each element. We can replace the whole loop by just the following:

array_walk($books, $addTaxes, 0.16);

The callable that array_walk receives needs to take at least two arguments: the value and the index of the current element of the array, and thus, the $index argument that we were forced to implement previously. It can optionally take extra arguments, which will be the extra arguments sent to array_walk – in this case, the 0.16 as $percentage.

Actually, anonymous functions are not the only callable in PHP. We can send normal functions and even class methods. Let’s see how:

function addTaxes(array &$book, $index, $percentage) {
if (isset($book['price'])) {
$book['price'] += round($percentage * $book['price'], 2);
}
}
class Taxes {
public static function add(array &$book, $index, $percentage)
{
if (isset($book['price'])) {
$book['price'] += round($percentage * $book['price'], 2);
}
}
public function addTaxes(array &$book, $index, $percentage)
{
if (isset($book['price'])) {
$book['price'] += round($percentage * $book['price'], 2);
}
}
}
// using normal function
array_walk($books, 'addTaxes', 0.16);
var_dump($books);
// using static class method
array_walk($books, ['Taxes', 'add'], 0.16);
var_dump($books);
// using class method
array_walk($books, [new Taxes(), 'addTaxes'], 0.16);
var_dump($books);

In the preceding example, we can see how we can use each case as a callable. For normal methods, just send the name of the method as a string. For static methods of a class, send an array with the name of the class in a way that PHP understands, and the name of the method, both as strings.

To use a normal method of a class, you need to send an array with an instance of that class and the method name as a string.

Anonymous functions can be used as callable, just as any other function or method can.

2. One of the things is that anonymous functions are variables, and so they have all the advantages—or disadvantages—that a variable has. That includes scope—that is, the function is defined inside a scope, and as soon as this scope ends, the function will no longer be accessible.

That can be useful if your function is extremely specific to that bit of code, and there is no way we will want to reuse it somewhere else.

3. Since it is nameless, we will not have conflicts with any other existing function. There is another benefit in using anonymous functions: inheriting variables from the parent scope.

When we define an anonymous function, we can specify some variable from the scope where it is defined with the keyword use, and use it inside the function.

The value of the variable will be the one it had at the moment of declaring the function, even if it is updated later. Let’s see an example:

Use of keyword “use”:

$percentage = 0.16;
$addTaxes = function (array &$book, $index) use ($percentage) {
if (isset($book['price'])) {
$book['price'] += round($percentage * $book['price'], 2);
}
};
$percentage = 100000;
array_walk($books, $addTaxes);
var_dump($books);

The preceding example shows us how to use the keyword use. This is useful, as it liberates us from having to send $percentage everywhere we want to use the function $addTaxes.

If there is a scenario where we really need to have the updated value of the used variables, we can declare them as
a reference as we would with a normal function’s argument:

$percentage = 0.16;
$addTaxes = function (array &$book, $index) use (&$percentage) {
if (isset($book['price'])) {
$book['price'] += round($percentage * $book['price'], 2);
}
};
array_walk($books, $addTaxes, 0.16);
var_dump($books);
$percentage = 100000;
array_walk($books, $addTaxes, 0.16);
var_dump($books);

In this last example, the first array_walk used the original value 0.16, as that was still the value of the variable. But on the second call, $percentage had already changed, and it affected the result of the anonymous function.

Leave a Comment

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