Función Flecha

Las funciones flecha fueron introducidas en PHP 7.4 como una sintaxis más concisa para las funciones anónimas.

Las funciones anónimas como las funciones flecha son implementadas utilizando la clase Closure.

Las funciones flecha tienen la forma básica fn (argument_list) => expr.

Las funciones flecha soportan las mismas funcionalidades que las funciones anónimas, a excepción de que el uso de las variables del ámbito padre es automático.

Cuando una variable utilizada en la expresión es definida en el ámbito padre, será implícitamente capturada por valor. En el siguiente ejemplo, las funciones $fn1 y $fn2 se comportan de manera idéntica.

Ejemplo #1 Las funciones flecha capturan las variables por valor automáticamente

<?php

$y
= 1;

$fn1 = fn($x) => $x + $y;
// equivalente a usar $y por valor:
$fn2 = function ($x) use ($y) {
return
$x + $y;
};

var_export($fn1(3));
?>

El resultado del ejemplo sería:

4

Esto también funciona si las funciones flecha están anidadas:

Ejemplo #2 Las funciones flecha capturan las variables por valor automáticamente, incluso anidadas

<?php

$z
= 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Muestra 51
var_export($fn(5)(10));
?>

De manera similar a las funciones anónimas, la sintaxis de las funciones flecha permite firmas de función arbitrarias, esto incluye los tipos de parámetros y de retorno, valores por defecto, variables, así como el paso y retorno por referencia. Todos los siguientes ejemplos son funciones flecha válidas:

Ejemplo #3 Ejemplos de funciones flecha

<?php

fn(array $x) => $x;
static fn(
$x): int => $x;
fn(
$x = 42) => $x;
fn(&
$x) => $x;
fn&(
$x) => $x;
fn(
$x, ...$rest) => $rest;

?>

Las funciones flecha enlazan las variables por valor. Esto es aproximadamente equivalente a realizar un use($x) para cada variable $x utilizada dentro de la función flecha. Un enlace por valor significa que no es posible modificar un valor del ámbito exterior. Las funciones anónimas pueden ser utilizadas en su lugar para enlaces por referencia.

Ejemplo #4 Los valores del ámbito exterior no pueden ser modificados por las funciones flecha

<?php

$x
= 1;
$fn = fn() => $x++; // No tiene efecto
$fn();
var_export($x); // Muestra 1

?>

Historial de cambios

Versión Descripción
7.4.0 Las funciones flecha están ahora disponibles.

Notas

Nota: Es posible utilizar func_num_args(), func_get_arg(), y func_get_args() desde el interior de una función flecha.

add a note

User Contributed Notes 5 notes

up
45
InvisibleSmiley
4 years ago
Unlike anonymous functions, arrow functions cannot have a void return type declaration.

May seem obvious, but if you thought you could make use of the benefits of arrow functions (using variables from the parent scope) to simplify a function or method call, keep in mind that this is only possible if you do NOT tell PHP that the arrow function does indeed return void.
up
41
Koushil Mankali
4 years ago
In example 4 (Values from the outer scope cannot be modified by arrow functions)

<?php

$x
= 1;
$fn = fn() => $x++; // Has no effect
$fn();
var_export($x); // Outputs 1

?>

Here we can use reference variable in fn(&$x) and pass the value from function call $fn($x) so that we will get the output as expected with out using Anonymous functions.

Example:

<?php

$x
= 1;
$fn = fn(&$x) => $x++;
$fn($x);
var_export($x);

?>

Output : 2 (as expected)

But here it will not take values from parent scope automatically but we have to pass them explicitly.
up
10
aaronw at catalyst dot net dot nz
4 months ago
If you're a JavaScript developer, here are the similarities and differences to JS arrow functions:

Same:
- Makes an anonymous function
- Binds the value of "$this" to its value in the parent scope.
- (along with all other variables of the parent scope. See note below)

Different:
- You must write "fn()" instead of just "()"
- The function body is limited to just ONE expression
- So no multi-line function bodies with "{" and "}"

Same and Different at the same time:
- Binds ALL the variables of the parent scope
- In JavaScript all functions are closures, binding to the variables in their parent scope (except for "this").
- But in PHP, normal anonymous functions (defined with "function() {}") do NOT get access to the parent scope, unless they explicitly declare a closure with keyword "use"
- PHP arrow functions, on the other hand, automatically bind to ALL variables in the parent scope. So, this makes them behave the same as JS functions, but be aware that in PHP this is special behavior unique to arrow functions.
up
23
itsunclexo at gmail dot com
4 years ago
As you already know, variable bindings occur in arrow functions by "by-value". That means, an arrow function returns a copy of the value of the variable used in it from the outer scope.

Now let us see an example of how a arrow function returns a reference instead of a copy of a value.

<?php

$x
= 0;

$fn = fn &(&$x) => $x; // Returns a reference

$y = &$fn($x); // Now $y represents the reference

var_dump($y); // Outputs: 0

$y = 3; // Changing value of $y affects $x

var_dump($x); // Ouputs: 3

?>
up
14
dexen dot devries at gmail dot com
4 years ago
Beware compact() not being able to access (import) variables from external scope (known in versions: 7.4.0, 7.4.8) (bug: https://bugs.php.net/bug.php?id=78970).

A workaround is available - use the variable directly; this will cause it to be imported into the arrow function's namespace and make it available to the compact() too.

<?php
$aa
= 111;
$accessing_variable_works = fn($bb) => [ $aa, $bb ];
$compact_is_broken = fn($bb) => compact('aa', 'bb');
$compact_can_work_with_workaround = fn($bb) => compact('aa', 'bb') + ['workaround' => $aa];
var_dump($accessing_variable_works(333));
var_dump($compact_is_broken(555));
var_dump($compact_can_work_with_workaround(777));
?>

result:
array(2) {
[0]=>
int(111)
[1]=>
int(333)
}
PHP Notice: compact(): Undefined variable: aa in /home/m/vlt/guitar/tlb/s/public_html/index.php on line 9
array(1) {
["bb"]=>
int(555)
}
array(3) {
["aa"]=>
int(111)
["bb"]=>
int(777)
["workaround"]=>
int(111)
}
To Top