Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions language/functions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1737,6 +1737,170 @@ Warning: Cannot bind an instance to a static closure in %s on line %d
</sect2>

</sect1>
<sect1 xml:id="functions.arrow">
<title>Arrow Functions</title>

<simpara>
Arrow functions were introduced in PHP 7.4 as a more concise syntax for
<link linkend="functions.anonymous">anonymous functions</link>.
</simpara>
<simpara>
Both anonymous functions and arrow functions are implemented using the
<link linkend="class.closure"><classname>Closure</classname></link> class.
</simpara>

<simpara>
Arrow functions have the basic form
<code>fn (argument_list) =&gt; expr</code>.
</simpara>

<simpara>
Arrow functions support the same features as
<link linkend="functions.anonymous">anonymous functions</link>,
except that using variables from the parent scope is always automatic.
</simpara>

<simpara>
When a variable used in the expression is defined in the parent scope
it will be implicitly captured by-value.
In the following example, the functions <varname>$fn1</varname> and
<varname>$fn2</varname> behave the same way.
</simpara>

<para>
<example>
<title>Arrow functions capture variables by value automatically</title>
<programlisting role="php">
<![CDATA[
<?php

$y = 1;

$fn1 = fn($x) => $x + $y;
// equivalent to using $y by value:
$fn2 = function ($x) use ($y) {
return $x + $y;
};

var_export($fn1(3));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
4
]]>
</screen>
</example>
</para>
<simpara>
This also works if the arrow functions are nested:
</simpara>
<para>
<example>
<title>Arrow functions capture variables by value automatically, even when nested</title>
<programlisting role="php">
<![CDATA[
<?php

$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Outputs 51
var_export($fn(5)(10));
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Similarly to anonymous functions,
the arrow function syntax allows arbitrary function signatures,
including parameter and return types, default values, variadics,
as well as by-reference passing and returning.
All of the following are valid examples of arrow functions:
</simpara>
<para>
<example>
<title>Examples of arrow functions</title>
<programlisting role="php">
<![CDATA[
<?php

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

?>
]]>
</programlisting>
</example>
</para>
<simpara>
Arrow functions use by-value variable binding.
This is roughly equivalent to performing a <code>use($x)</code> for every
variable <varname>$x</varname> used inside the arrow function.
A by-value binding means that it is not possible to modify any values
from the outer scope.
<link linkend="functions.anonymous">Anonymous functions</link>
can be used instead for by-ref bindings.
</simpara>
<para>
<example>
<title>Values from the outer scope cannot be modified by arrow functions</title>
<programlisting role="php">
<![CDATA[
<?php

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

?>
]]>
</programlisting>
</example>
</para>

<sect2 role="changelog">
&reftitle.changelog;
<para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>7.4.0</entry>
<entry>
Arrow functions became available.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>

<sect2 role="notes">
&reftitle.notes;
<note>
<simpara>
It is possible to use <function>func_num_args</function>,
<function>func_get_arg</function>, and <function>func_get_args</function>
from within an arrow function.
</simpara>
</note>
</sect2>
</sect1>

</chapter>

Expand Down