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
Last revisionBoth sides next revision
rfc:auto-capture-lambda [2021/03/22 21:56] crellrfc:auto-capture-lambda [2021/03/24 15:54] crell
Line 1: Line 1:
-====== PHP RFC: Auto-capturing lambdas ======+====== PHP RFC: Auto-capturing multi-statement closures ======
   * Version: 0.9   * Version: 0.9
   * Date: 2021-03-22   * Date: 2021-03-22
Line 8: Line 8:
 ===== Introduction ===== ===== 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.+Closures (also known as lambdas or anonymous functions), 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 closures 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.+<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 
 +   // ... 
 + 
 +   return $x + $y; 
 +}; 
 +</code> 
 + 
 +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; 
 +}; 
 +</code> 
 + 
 +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 ===== ===== Proposal =====
Line 21: Line 45:
  
 // A named, globally available function. // A named, globally available function.
-// No values are auto-captured from the environment. +// No variables are auto-captured from the environment. 
-// The body is a series of statements, with possibly a return statement.+// The body is a statement list, with possibly a return statement.
 function foo($a, $b, $c): int { function foo($a, $b, $c): int {
   return $a * $b * $c;   return $a * $b * $c;
Line 28: Line 52:
  
 // An anonymous, locally available function. // An anonymous, locally available function.
-// Values are explicitly captured lexically.  +// Variables are explicitly captured lexically.  
-// The body is a series of statements, with possibly a return statement.+// The body is a statement list, with possibly a return statement.
 $foo = function ($a, $b) use ($c) { $foo = function ($a, $b) use ($c) {
   return $a * $b * $c;   return $a * $b * $c;
Line 35: Line 59:
  
 // An anonymous, locally available function. // An anonymous, locally available function.
-// Values are auto-captured lexically.+// Variables are auto-captured lexically.
 // The body is a single-expression, whose value is returned. // The body is a single-expression, whose value is returned.
 $foo = fn($a, $b): int => $a * $b * $c; $foo = fn($a, $b): int => $a * $b * $c;
Line 44: Line 68:
 The [[rfc:short-functions|Short Functions]] RFC seeks to add one additional combination: named, no-capture, single-expression. 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.+This RFC seeks to add a different combination: anonymous, auto-capture, statement list.
  
 The remaining combinations would be: The remaining combinations would be:
Line 50: Line 74:
   * 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, 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.   * 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.+  * anonymous function, manual-capture, expression - While this form would be possible to add, its use cases are limited.  The existing short-closure syntax is superior in nearly all cases.
  
-==== Auto-capture multi-statement lambdas ====+==== Auto-capture multi-statement closures ====
  
 Specifically, this RFC adds the following syntax: Specifically, this RFC adds the following syntax:
Line 58: Line 82:
 <code php> <code php>
 // An anonymous, locally available function. // An anonymous, locally available function.
-// Values are auto-captured lexically. +// Variables are auto-captured lexically. 
-// The body is a series of statementspotentially ending in a return statement;+// The body is a statement listwith possibly a return statement;
 $c = 1; $c = 1;
-$foo = fn($a, $b) {+$foo = fn($a, $b):int {
   $val = $a * $b;   $val = $a * $b;
   return $val * $c;   return $val * $c;
Line 67: Line 91:
 </code> </code>
  
-The syntax choice here, in combination with short-functions, leads to the following consistent syntactic meanings:+The syntax choice here, in combination with the short-functions RFC, 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()''.)   * 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''.   * ''{ ... }'' denotes a statement list, potentially ending in a ''return''.
   * The ''function'' keyword indicates a function that has no auto-capture.   * The ''function'' keyword indicates a function that has no auto-capture.
-  * The ''fn'' keyword indicates a function that will auto-capture, by value. +  * The ''fn'' keyword indicates a function that will auto-capture variables, 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.+  * 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. These rules are easily recognizable and learnable by developers.
Line 81: Line 105:
 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. 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? ====+==== What about long-closures? ====
  
-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:+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 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.   * When it is desirable to capture a variable by reference.  Such use case are rare but do exist.
 +
 +<code php>
 +// This remains the only way to capture by reference.
 +$c = 1;
 +$f = function($a, $b) use (&$c) {
 +  $c = $a * $b;
 +};
 +</code>
  
 ==== Multi-line expressions ==== ==== Multi-line expressions ====
Line 120: Line 152:
  
 ===== Open Issues ===== ===== Open Issues =====
-Make sure there are no open issues when the vote starts!+ 
 +None.
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
Line 133: Line 166:
  
 <code php> <code php>
-$GLOBALS['c'= 1;+// Global scope 
 +$c = 1;
  
-fn foo($a, $b) {+fn foo($a, $b): int {
   $val = $a * $b;   $val = $a * $b;
   return $val * $c;   return $val * $c;
 } }
  
-fn foo($a, $b) => $a * $b * $c;+fn foo($a, $b): int => $a * $b * $c;
  
-$foo = fn($a, $b) use ($c) => $a * $b * $c;+$foo = fn($a, $b) use ($c): int => $a * $b * $c;
 </code> </code>
  
Line 153: Line 187:
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
-Patch is in progress from Nuno.  It will be included prior to the official start of discussion.+Pull Request: https://github.com/php/php-src/pull/6246
  
 ===== Implementation ===== ===== Implementation =====
rfc/auto-capture-lambda.txt · Last modified: 2021/03/24 15:58 by crell