rfc:auto-capture-lambda

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:auto-capture-lambda [2021/03/22 21:56] crellrfc:auto-capture-lambda [2021/03/24 15:58] (current) – Deprecate page. crell
Line 1: Line 1:
-====== PHP RFC: Auto-capturing lambdas ====== +[[rfc:auto-capture-closure|MovedSee the Auto-capturing multi-statement closures RFC]]
-  * Version: 0.9 +
-  * Date: 2021-03-22 +
-  * Author: Nuno Maduro (enunomaduro@gmail.com), Larry Garfield (larry@garfieldtech.com) +
-  * Status: Draft +
-  * First Published at: http://wiki.php.net/rfc/auto-capture-lambda +
- +
-===== Introduction ===== +
- +
-Lambdas have become increasingly powerful and useful in PHP in recent versions.  In their current form they have two versions, long and short.  Unfortunately, these two syntaxes have different, mutually-incompatible benefits.  This RFC proposes a syntax for lambdas that combines the benefits of both for those situations where that is warranted. +
- +
-Specifically, it 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 values are auto-captured from the environment. +
-// The body is a series of statements, with possibly a return statement. +
-function foo($a, $b, $c): int { +
-  return $a * $b * $c; +
-+
- +
-// An anonymous, locally available function. +
-// Values are explicitly captured lexically.  +
-// The body is a series of statements, with possibly a return statement. +
-$foo = function ($a, $b) use ($c) { +
-  return $a * $b * $c; +
-}; +
- +
-// An anonymous, locally available function. +
-// Values are auto-captured lexically. +
-// The body is a single-expression, whose value is returned. +
-$foo = fn($a, $b): int => $a * $b * $c; +
-</code> +
- +
-That is, a function may be named or local/anonymous, auto-capture or not, and a statement list or single expression.  That means there are 8 possible combinations of properties, of which only three are currently supported. +
- +
-The [[rfc:short-functions|Short Functions]] RFC seeks to add one additional combination: named, no-capture, single-expression. +
- +
-This RFC seeks to add a different combination: local, auto-capture, statement list. +
- +
-The remaining combinations would be: +
- +
-  * named function, auto-capture, statement list - This is of little use in practice as there is nothing to auto-capture, except potentially global variables. +
-  * named function, auto-capture, expression - Ibid. +
-  * anonymous function, manual-capture, expression - While this form would be possible to add, its use cases are limited.  The existing short-lambda syntax is superior in nearly all cases. +
- +
-==== Auto-capture multi-statement lambdas ==== +
- +
-Specifically, this RFC adds the following syntax: +
- +
-<code php> +
-// An anonymous, locally available function. +
-// Values are auto-captured lexically. +
-// The body is a series of statements, potentially ending in a return statement; +
-$c = 1; +
-$foo = fn($a, $b) { +
-  $val = $a * $b; +
-  return $val * $c; +
-}; +
-</code> +
- +
-The syntax choice here, in combination with short-functions, leads to the following consistent syntactic meanings: +
- +
-  * The ''=>'' sigil always means "evaluates to the expression on the right," in all circumstances.  (Named functions, anonymous functions, arrays, and ''match()''.) +
-  * ''{ ... }'' denotes a statement list, potentially ending in a ''return''+
-  * The ''function'' keyword indicates a function that has no auto-capture. +
-  * The ''fn'' keyword indicates a function that will auto-capture, by value. +
-  * A function with a name is declared globally at compile time.  A function without a name is declared locally as a lambda 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-lambdas? ==== +
- +
-The existing multi-line lambda 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.  Such use case are rare but do exist. +
- +
-==== Multi-line expressions ==== +
- +
-There has been related discussion of multi-line expressions, specifically in the context of ''mach()'' arms.  We considered whether multi-line expressions made sense as an alternative approach, but decided against it as that introduces considerably more edge cases both syntactically and in the engine. +
- +
-As a side benefit, the syntax proposed here does offer a somewhat round-about way to have a multi-line ''match()'' arm.  This is not a deliberate feature of the RFC, but more of a convenient side-effect. +
- +
-<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; +
-  }(), +
-}; +
-</code> +
- +
-While sub-optimal, it may be sufficient for the few times that a multi-statement ''match()'' arm is needed. +
- +
-===== Backward Incompatible Changes ===== +
- +
-None. +
- +
-===== Proposed PHP Version(s) ===== +
- +
-PHP 8.1. +
- +
-===== Open Issues ===== +
-Make sure there are no open issues when the vote starts! +
- +
-===== 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, they would be: +
- +
-<code php> +
-$GLOBALS['c'= 1; +
- +
-fn foo($a, $b) { +
-  $val = $a * $b; +
-  return $val * $c; +
-+
- +
-fn foo($a, $b) => $a * $b * $c; +
- +
-$foo = fn($a, $b) use ($c) => $a * $b * $c; +
-</code> +
- +
-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 ===== +
- +
-Patch is in progress from Nuno.  It will be included prior to the official start of discussion. +
- +
-===== Implementation ===== +
-After the project is implemented, this section should contain  +
-  - 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:short-functions|PHP RFC: Short Functions]+
- +
-===== Rejected Features ===== +
-Keep this updated with features that were discussed on the mail lists.+
rfc/auto-capture-lambda.1616450193.txt.gz · Last modified: 2021/03/22 21:56 by crell