What are the main differences between Arrow Function and Closures (anonymous functions) in PHP?

Asked

Viewed 179 times

4

In version 7.4 of PHP, it was implemented Arrow Functions.

Example:

$double = fn($x) => $x * 2;
var_dump($double(4)); // int(8)

Which could be done as follows in previous versions:

$double = function ($x) { 
   return $x * 2; 
}

I know this helps a lot to improve writing to callbacks in the case of functions such as array_map or usort.

But beyond that, there is some difference of functioning, or even internal, between Arrow Functions and Closures?

1 answer

5


Influence of fashion that Arrow functions in Javascript became, no doubt.

In short, the differences are:

  • Syntactic difference (anonymous functions are syntactically different from new functions in arrow).
  • Unlike anonymous functions, which accept statements and expressions (within a block ({ ... }), Arrow functions only have a single expression. A Arrow Function does not have a block, so it can only evaluate (and return) a single expression.
  • Differences in scope (reading and modification of higher scope names behave differently).

Reading of variables of higher scope

As Arrow functions inherit all names from higher scopes automatically. In computer science, this behavior is called enclosure (of the English closure). As Arrow functions PHP implemented this system in a very similar way to closures javascript.

Just be careful not to confuse that name with the class Closure, that PHP has had for some time!

Thus, with the Arrow functions you can use any kind of name of any parent scope without explicit indications. With the old anonymous functions, you should "declare" that you are using a higher scope variable using the directive use.

See an example of code that uses anonymous function:

<?php
$exp = 3;
$nums = [1, 2, 3, 4, 5];

// Função anônima.
// Note que preciso declarar o uso de `$exp` explicitamente.
$result = array_map(function ($num) use ($exp) {
  return pow($num, $exp);
}, $nums);

print_r($result); //=> [1, 8, 27, 64, 125]

In the example above, if the directive use ($exp) had it not been used, such a variable would be undefined in the scope of the function. It would receive a warning such as:

PHP Warning:  Undefined variable $exp in /Users/luiz/Dev/.Scripts/arrow-fn.php on line 9

This explicit use statement is not required in Arrow functions. Behold:

<?php
$exp = 3;
$nums = [1, 2, 3, 4, 5];

// Arrow function.
// Escopo léxico parente é "herdado":
$result = array_map(fn($num) => pow($num, $exp), $nums);

print_r($result); //=> [1, 8, 27, 64, 125]

I take the previous example to highlight the fact that Arrow functions can only return the result of the evaluation of a single expression. In the above example, the expression we return is the result of the application of the function pow (potentiation).

Impossibility of modification of variables of higher scope

An external scope variable cannot be modified by a Arrow Function. If you try to make a modification, it will be ignored. See the example of the documentation[1]:

<?php
$x = 1;

$fn = fn() => $x++; // Não tem efeito
$fn();

print_r($x); //=> 1 (Não foi modificada!)

No doubt another example of the influence PHP is showing on functional programming, which preaches for the immutability of values. However, the question remains: does PHP really need to adhere to these principles?

  • +1, but I must point out that the only problematic part of the answer is this statement: "The Arrow functions inherit all top-scope names automatically. This is called closure". I don’t mean a problem of the answer itself, but the name that PHP gave, because it uses Closure to refer to the anonymous function [the anonymous function of versions 7.3 <=]. But the same do not include the higher scope variables automatically. I had a colleague of mine who said that PHP misnamed, since Closure should inherit variables, but in PHP only works with use($var)

  • ... Only with the implementation of Arrow Function that this has become true. Now it’s doubtful if this was another internal PHP mess.

  • 1

    Thanks for the comment, @Wallacemaxters. I edited this excerpt to try to clarify a little more. Improved? :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.