rfc:auto-capture-lambda
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:auto-capture-lambda [2021/03/24 15:47] – Comment. crell | rfc:auto-capture-lambda [2021/03/24 15:58] (current) – Deprecate page. crell | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== PHP RFC: Auto-capturing multi-line closures ====== | + | [[rfc: |
- | * Version: 0.9 | + | |
- | * Date: 2021-03-22 | + | |
- | * Author: Nuno Maduro (enunomaduro@gmail.com), | + | |
- | * Status: Draft | + | |
- | * First Published at: http:// | + | |
- | + | ||
- | ===== Introduction ===== | + | |
- | + | ||
- | Closures (also known as lambdas or anonymous functions), have become increasingly powerful and useful in PHP in recent versions. | + | |
- | + | ||
- | <code php> | + | |
- | // As of 8.0: | + | |
- | + | ||
- | $y = 1; | + | |
- | + | ||
- | $fn1 = fn($x) => $x + $y; // auto-capture + single expression | + | |
- | + | ||
- | $fn2 = function ($x) use ($y): int { // manual-capture + statement list | + | |
- | // ... | + | |
- | + | ||
- | | + | |
- | }; | + | |
- | </ | + | |
- | + | ||
- | The proposed syntax combines the auto-capture and multi-line capabilities into a single syntax: | + | |
- | + | ||
- | <code php> | + | |
- | $fn3 = fn ($x): int { // auto-capture + statement list | + | |
- | // ... | + | |
- | + | ||
- | return $x + $y; | + | |
- | }; | + | |
- | </ | + | |
- | + | ||
- | This RFC has also been designed in concert with the [[rfc:short-functions|Short Functions]] RFC, such that the syntax choices of both RFCs are mutually complementary in a logical, predictable fashion and described below. | + | |
- | + | ||
- | ===== Proposal ===== | + | |
- | + | ||
- | ==== Background ==== | + | |
- | + | ||
- | As of PHP 8.0, the following syntax around functions has the following meaning: | + | |
- | + | ||
- | <code php> | + | |
- | + | ||
- | // A named, globally available function. | + | |
- | // No variables are auto-captured from the environment. | + | |
- | // The body is a statement list, with possibly a return statement. | + | |
- | function foo($a, $b, $c): int { | + | |
- | return $a * $b * $c; | + | |
- | } | + | |
- | + | ||
- | // An anonymous, locally available function. | + | |
- | // Variables are explicitly captured lexically. | + | |
- | // The body is a statement list, with possibly a return statement. | + | |
- | $foo = function ($a, $b) use ($c) { | + | |
- | return $a * $b * $c; | + | |
- | }; | + | |
- | + | ||
- | // An anonymous, locally available function. | + | |
- | // Variables are auto-captured lexically. | + | |
- | // The body is a single-expression, | + | |
- | $foo = fn($a, $b): int => $a * $b * $c; | + | |
- | </ | + | |
- | + | ||
- | That is, a function may be named or local/ | + | |
- | + | ||
- | The [[rfc:short-functions|Short Functions]] RFC seeks to add one additional combination: | + | |
- | + | ||
- | This RFC seeks to add a different combination: | + | |
- | + | ||
- | The remaining combinations would be: | + | |
- | + | ||
- | * named function, auto-capture, | + | |
- | * named function, auto-capture, | + | |
- | * anonymous function, manual-capture, | + | |
- | + | ||
- | ==== Auto-capture | + | |
- | + | ||
- | Specifically, | + | |
- | + | ||
- | <code php> | + | |
- | // An anonymous, locally available function. | + | |
- | // Variables are auto-captured lexically. | + | |
- | // The body is a statement list, with possibly a return statement; | + | |
- | $c = 1; | + | |
- | $foo = fn($a, $b):int { | + | |
- | $val = $a * $b; | + | |
- | return $val * $c; | + | |
- | }; | + | |
- | </ | + | |
- | + | ||
- | The syntax choice here, in combination with the short-functions RFC, leads to the following consistent syntactic meanings: | + | |
- | + | ||
- | * The '' | + | |
- | * '' | + | |
- | * The '' | + | |
- | * The '' | + | |
- | * A function with a name is declared globally at compile time. A function without a name is declared locally as a closure at runtime. | + | |
- | + | ||
- | These rules are easily recognizable and learnable by developers. | + | |
- | + | ||
- | ==== Methods ==== | + | |
- | + | ||
- | As methods cannot be anonymous, there are no impacts on methods from this RFC. The short-functions RFC does address methods, and does so in a way that is completely consistent with the syntactic rules defined above. | + | |
- | + | ||
- | ==== What about long-closures? | + | |
- | + | ||
- | The existing multi-line closure syntax remains valid, and there is no intent to deprecate it. It is likely to become less common in practice, but it still has two use cases where it will be necessary: | + | |
- | + | ||
- | * When it is desirable to capture variables explicitly, such as to avoid name collision. | + | |
- | * When it is desirable to capture a variable by reference. | + | |
- | + | ||
- | <code php> | + | |
- | // This remains the only way to capture by reference. | + | |
- | $c = 1; | + | |
- | $f = function($a, | + | |
- | $c = $a * $b; | + | |
- | }; | + | |
- | </ | + | |
- | + | ||
- | ==== Multi-line expressions ==== | + | |
- | + | ||
- | There has been related discussion of multi-line expressions, | + | |
- | + | ||
- | As a side benefit, the syntax proposed here does offer a somewhat round-about way to have a multi-line '' | + | |
- | + | ||
- | <code php> | + | |
- | $b = ...; | + | |
- | $c = ...; | + | |
- | $ret = match ($a) { | + | |
- | 1, 3, 5 => fn() { | + | |
- | $val = $a * $b; | + | |
- | return $val * $c; | + | |
- | }(), | + | |
- | 2, 4, 6 => fn() { | + | |
- | $val = $a + $b; | + | |
- | return $val + $c; | + | |
- | }(), | + | |
- | }; | + | |
- | </ | + | |
- | + | ||
- | While sub-optimal, | + | |
- | + | ||
- | ===== Backward Incompatible Changes ===== | + | |
- | + | ||
- | None. | + | |
- | + | ||
- | ===== Proposed PHP Version(s) ===== | + | |
- | + | ||
- | PHP 8.1. | + | |
- | + | ||
- | ===== Open Issues ===== | + | |
- | + | ||
- | None. | + | |
- | + | ||
- | ===== Unaffected PHP Functionality ===== | + | |
- | + | ||
- | Existing function syntax continues to work precisely as it does now. Only new combinations are possible. | + | |
- | + | ||
- | ===== Future Scope ===== | + | |
- | + | ||
- | The proposal section detailed three additional possible combinations of function functionality that are not included here. While it is not likely that they have much use, the pattern here clearly lays out what they would be were a future RFC to try and implement them. | + | |
- | + | ||
- | Specifically, | + | |
- | + | ||
- | <code php> | + | |
- | // Global scope | + | |
- | $c = 1; | + | |
- | + | ||
- | fn foo($a, $b): int { | + | |
- | $val = $a * $b; | + | |
- | return $val * $c; | + | |
- | } | + | |
- | + | ||
- | fn foo($a, $b): int => $a * $b * $c; | + | |
- | + | ||
- | $foo = fn($a, $b) use ($c): int => $a * $b * $c; | + | |
- | </ | + | |
- | + | ||
- | Those versions are //not// included in this RFC. | + | |
- | + | ||
- | ===== Proposed Voting Choices ===== | + | |
- | + | ||
- | This is a simple Yes/No vote, requiring 2/3 to pass. | + | |
- | + | ||
- | ===== Patches and Tests ===== | + | |
- | + | ||
- | Pull Request: https:// | + | |
- | + | ||
- | ===== Implementation ===== | + | |
- | After the project is implemented, | + | |
- | - the version(s) it was merged into | + | |
- | - a link to the git commit(s) | + | |
- | - a link to the PHP manual entry for the feature | + | |
- | - a link to the language specification section (if any) | + | |
- | + | ||
- | ===== References ===== | + | |
- | [[rfc: | + | |
- | + | ||
- | ===== Rejected Features ===== | + | |
- | Keep this updated with features that were discussed on the mail lists. | + |
rfc/auto-capture-lambda.txt · Last modified: 2021/03/24 15:58 by crell