rfc:arrow_functions
Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
rfc:arrow_functions [2016/10/06 15:51] levim Remove example with array body |
rfc:arrow_functions [2018/06/28 14:35] levim Withdraw |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Arrow Functions ====== | ====== PHP RFC: Arrow Functions ====== | ||
- | * Version: 1.2 | + | * Version: 1.3 |
* Date: 2016-08-14 | * Date: 2016-08-14 | ||
* Author: Levi Morrison < | * Author: Levi Morrison < | ||
* Author: Bob Weinand < | * Author: Bob Weinand < | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
Line 10: | Line 10: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | Anonymous functions and closures can be verbose even though sometimes they are quite simple and contain only a single expression. Additionally, | + | Anonymous functions and closures can be verbose even though sometimes they are quite simple and contain only a single expression. Additionally, |
As an example of the declaration overhead, consider this function that [[https:// | As an example of the declaration overhead, consider this function that [[https:// | ||
< | < | ||
- | return array_map(function($x) use ($arr) { return $arr[$x]; }, $keys); | + | return array_map(function ($x) use ($arr) { return $arr[$x]; }, $keys); |
}</ | }</ | ||
- | The closure performs a single operation < | + | The closure performs a single operation < |
< | < | ||
- | return array_map($x => $arr[$x], $keys); | + | return array_map(fn($x) => $arr[$x], $keys); |
}</ | }</ | ||
- | This reduces the amount of boilerplate from 30 characters down to 5. | + | This reduces the amount of boilerplate from 30 characters down to 8. |
See more examples in the [[# | See more examples in the [[# | ||
Line 31: | Line 31: | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | Arrow functions have a few forms: | + | Arrow functions have the following form: |
<PHP> | <PHP> | ||
- | (parameter_list) => expr | + | fn(parameter_list) => expr |
- | singleParam => expr | + | |
- | () => expr | + | |
</ | </ | ||
- | The '' | + | The '' |
<PHP> | <PHP> | ||
- | $mul2 = ($x) => $x * 2; | + | $mul2 = fn($x) => $x * 2; |
$mul2(3); // evaluates to 6 | $mul2(3); // evaluates to 6 | ||
</ | </ | ||
- | |||
- | If there is only a single parameter for the arrow function then the parenthesis around the parameter list can be omitted: | ||
- | |||
- | <PHP> | ||
- | $mul2 = $x => $x * 2; | ||
- | |||
- | $mul2(3); // evaluates to 6 | ||
- | </ | ||
- | |||
- | If there are no parameters then the parentheses are required as probably expected: | ||
- | |||
- | < | ||
When a variable in the expression is defined in the parent scope it will be captured implicitly by-value. | When a variable in the expression is defined in the parent scope it will be captured implicitly by-value. | ||
Line 65: | Line 51: | ||
$y = 1; | $y = 1; | ||
- | $versionA = $x => $x + $y; | + | $versionA = fn($x) => $x + $y; |
- | $versionB = function($x) use($y) { | + | $versionB = function ($x) use ($y) { |
return $x + $y; | return $x + $y; | ||
};</ | };</ | ||
Line 76: | Line 62: | ||
==== Type Declarations ==== | ==== Type Declarations ==== | ||
- | This RFC does not permit | + | This RFC does support |
- | ==== Ambiguities ==== | + | Here are some examples to show the syntax: |
- | Arrow functions have ambiguities with array key definitions and yield expressions that provide a key. | + | |
<PHP> | <PHP> | ||
- | // Does this mean: | + | fn (array $x) => $x |
- | // 1. Create an array key of`$x` and a value with `$x * 2` | + | fn (): int => 42 |
- | // 2. Create an array with one value that is an anonymous function | + | |
- | [$x => $x * 2] | + | |
- | + | ||
- | // Does this mean: | + | |
- | // 1. Yield a key of `$x` and a value with `$x * 2` | + | |
- | // 2. Yield an anonymous function | + | |
- | yield $x => $x * 2; | + | |
</ | </ | ||
- | These ambiguities are solved | + | ==== References ==== |
+ | Parameters and return values can be passed/ | ||
<PHP> | <PHP> | ||
- | // Create an array key of`$x` and a value with `$x * 2` | + | fn &(array &$xs) => $xs |
- | [$x => $x * 2]; | + | </PHP> |
- | // Create an array with one member that is an arrow function | + | ==== Static Arrow Functions ==== |
- | [($x => $x * 2)]; | + | The implementation currently supports static closures, for example < |
- | // Yield a key of `$x` and a value with `$x * 2` | + | ==== Ambiguities ==== |
- | yield $x => $x * 2; | + | Arrow functions have no ambiguities, |
+ | ==== Backward Incompatible Changes ==== | ||
+ | Unfortunately the '' | ||
- | // Yield an anonymous function | + | Ilija Tovilo analyzed the top 1,000 PHP repositories on GitHub to find usages of '' |
- | yield ($x => $x * 2); | + | |
- | </PHP> | + | |
- | + | ||
- | ==== Backward Incompatible Changes ==== | + | |
- | There are no backwards incompatible changes. | + | |
==== Patches and Tests ==== | ==== Patches and Tests ==== | ||
- | An old implementation with tests can be found here: https:// | + | An implementation with tests can be found here: https:// |
- | + | ||
- | ==== PHP Version ==== | + | |
- | This RFC targets PHP 7.NEXT, currently version 7.2. | + | |
==== Voting ==== | ==== Voting ==== | ||
Line 130: | Line 103: | ||
----- | ----- | ||
- | ==== Examples ==== | + | ===== Examples ===== |
- | + | ||
- | === Snippets | + | |
Taken from [[https:// | Taken from [[https:// | ||
Line 140: | Line 111: | ||
// with arrow function: | // with arrow function: | ||
- | $extended = $c => $callable($factory($c), | + | $extended = fn($c) => $callable($factory($c), |
- | This reduces the amount of boilerplate from 44 characters down to 4. | + | This reduces the amount of boilerplate from 44 characters down to 8. |
----- | ----- | ||
Line 153: | Line 124: | ||
// with arrow function | // with arrow function | ||
- | $this-> | + | $this-> |
- | This reduces the amount of boilerplate from 31 characters down to 4. | + | This reduces the amount of boilerplate from 31 characters down to 8. |
----- | ----- | ||
Line 162: | Line 133: | ||
< | < | ||
- | return function(... $args) use ($f) { | + | return function (... $args) use ($f) { |
return !$f(... $args); | return !$f(... $args); | ||
}; | }; | ||
Line 169: | Line 140: | ||
// with arrow function: | // with arrow function: | ||
function complement(callable $f) { | function complement(callable $f) { | ||
- | return (... $args) => !$f(... $args); | + | return |
}</ | }</ | ||
- | |||
- | === Longer Examples === | ||
- | |||
- | Taken from Pinq's example in their [[https:// | ||
- | |||
- | < | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | return [ | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ]; | ||
- | }); | ||
- | </ | ||
- | |||
- | With arrow functions: | ||
- | |||
- | < | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | -> | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ]); | ||
- | </ | ||
----- | ----- | ||
- | The following | + | The following |
< | < | ||
- | -> | + | -> |
return $v * 2; | return $v * 2; | ||
}) | }) | ||
- | -> | + | -> |
return $tmp + $v; | return $tmp + $v; | ||
}, 0); | }, 0); | ||
Line 222: | Line 159: | ||
// with arrow functions: | // with arrow functions: | ||
$result = Collection:: | $result = Collection:: | ||
- | ->map($v => $v * 2) | + | ->map(fn($v) => $v * 2) |
- | -> | + | -> |
echo $result; //6 | echo $result; //6 | ||
</ | </ | ||
- | ===== Future Scope ===== | + | ===== Future Scope: Multi-Statement Bodies |
- | + | ||
- | ==== Multi-Statement Bodies ==== | + | |
Some languages permit multi-statement closures with a syntax like: | Some languages permit multi-statement closures with a syntax like: | ||
rfc/arrow_functions.txt · Last modified: 2018/06/28 14:35 by levim