rfc:arrow_functions_v2

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:arrow_functions_v2 [2019/03/13 15:46] nikicrfc:arrow_functions_v2 [2020/04/18 14:54] – Less party sebastian
Line 6: Line 6:
   * Target version: PHP 7.4   * Target version: PHP 7.4
   * Implementation: https://github.com/php/php-src/pull/3941   * Implementation: https://github.com/php/php-src/pull/3941
-  * Status: Under Discussion+  * Status: Accepted
  
 ===== Introduction ===== ===== Introduction =====
  
 Anonymous functions in PHP can be quite verbose, even when they only perform a simple operation. Anonymous functions in PHP can be quite verbose, even when they only perform a simple operation.
-Partly this is due to a large amount of syntactic boilerplate, and party due to the need to manually+Partly this is due to a large amount of syntactic boilerplate, and partly due to the need to manually
 import used variables. This makes code using simple closures hard to read and understand. This RFC import used variables. This makes code using simple closures hard to read and understand. This RFC
 proposes a more concise syntax for this pattern. proposes a more concise syntax for this pattern.
Line 90: Line 90:
 </PHP> </PHP>
  
-==== Static arrow functions ====+==== $this binding and static arrow functions ====
  
-For the sake of completenessstatic arrow functions are supported using the syntax +Just like normal closures, the ''$this'' variablethe scope and the LSB scope are automatically bound when short closure is created inside a class method. For normal closuresthis can be prevented by prefixing them with ''static''For the sake of completeness this is also supported for arrow functions:
-<php>static fn($x) => $x</php>. A static arrow functionjust like static closure, will not +
-bind the ''$this'' variable.+
  
-Static closures are mainly (exclusively?used to avoid unnecessary cycles involving ''$this'', +<PHP> 
-which may result in delayed GC.+class Test { 
 +    public function method() { 
 +        $fn = fn() => var_dump($this); 
 +        $fn(); // object(Test)#1 { ... } 
 +         
 +        $fn = static fn() => var_dump($this); 
 +        $fn(); // Error: Using $this when not in object context 
 +    } 
 +
 +</PHP> 
 + 
 +Static closures are rarely used: They're mainly used to prevent ''$this'' cycles, which make GC behavior less predictable. Most code need not concern itself with this. 
 + 
 +It has been suggested that we could use this opportunity to change the ''$this'' binding semantics towards only binding ''$this'' if it is actually used inside the closure. Apart from GC effects, this would result in the same behavior. Unfortunately PHP has some implicit uses of ''$this''. For example ''Foo::bar()'' calls may inherit ''$this'' if it is compatible with the ''Foo'' scope. We could only carry out a conservative analysis of potential ''$this'' use, which would be unpredictable from a user perspective. As such, we prefer to keep the existing behavior of always binding ''$this''.
  
 ==== By-value variable binding ==== ==== By-value variable binding ====
Line 248: Line 259:
 ===== Vote ===== ===== Vote =====
  
-Simple yes/no vote.+Voting started 2019-04-17 and ends 2019-05-01. A 2/3 majority is required. 
 + 
 +<doodle title="Add arrow functions as described in PHP 7.4?" auth="nikic" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle>
  
 ===== Discussion ===== ===== Discussion =====
Line 425: Line 441:
 ~($x) => $x * $y ~($x) => $x * $y
 @($x) => $x * $y @($x) => $x * $y
 +
 +// Not possible, because _() is a valid function name, used as an alias for gettext()
 +_($x) => $x * $y
 </PHP> </PHP>
  
Line 447: Line 466:
 It would be possible to resolve this ambiguity by lexing namespaced names as a single token It would be possible to resolve this ambiguity by lexing namespaced names as a single token
 (removing support for whitespace inside them). This would, however, be a breaking change. (removing support for whitespace inside them). This would, however, be a breaking change.
 +
 +=== Using -> and --> as arrows ===
 +
 +As an alternative to ''%%=>%%'' the use of ''%%->%%'' and ''%%-->%%'' has been suggested. Any arrow syntax without a leading sigil would still be subject to the issues in the previous section, but these two in particular also conflict with existing syntax: ''%%->%%'' is already used for property access:
 +
 +<PHP>
 +($x) -> $x
 +// already valid, more typically written as:
 +$x->{$x}
 +</PHP>
 +
 +''%%-->%%'' is a combination of The post-decrement operator ''%%--%%'' and the greater-than operator ''>'':
 +
 +<PHP>
 +$x --> $x
 +// already valid, more typically written as:
 +$x-- > $x
 +</PHP>
 +
 +''%%-->%%'' would be valid when restricted to the form that uses parentheses, because ''%%($x)--%%'' is not legal code right now. Both arrows would be possible in conjunction with a leading symbol, but at that point any ambiguity is already resolved by the leading symbol and we may as well use ''%%=>%%''.
  
 === Different parameter list separators === === Different parameter list separators ===
Line 516: Line 555:
 This syntax is not viable in PHP, because ''[$x]($y)'' is already valid syntax, so this would run This syntax is not viable in PHP, because ''[$x]($y)'' is already valid syntax, so this would run
 into all the same parsing issues. into all the same parsing issues.
 +
 +=== Miscellaneous ===
 +
 +It has been suggested to use the ''%%\param_list => expr%%'' syntax (without wrapping the parameters in parentheses), which is very close to the syntax used by Haskell. This syntax is ambiguous, because the ''\'' may also be part of a fully qualified type name:
 +
 +<PHP>
 +[\T &$x => $y]
 +// could be
 +[\(T &$x) => $y)]
 +// or
 +[(\T & $x) => $y]
 +</PHP>
  
 ==== Binding behavior ==== ==== Binding behavior ====
Line 529: Line 580:
 <PHP> <PHP>
 $x = 1; $x = 1;
-$fn = () => $x++;+$fn = fn() => $x++;
 $fn(); $fn();
 var_dump($x); // By-value: 1 var_dump($x); // By-value: 1
Line 626: Line 677:
  
 <PHP> <PHP>
 +fn(params) => {
 +    stmt1;
 +    stmt2;
 +    return expr;
 +}
 +// or possibly just
 fn(params) { fn(params) {
     stmt1;     stmt1;
Line 691: Line 748:
 There are some possible variations of this, e.g. allow ''%%=>%%'' but not ''fn''. There are some possible variations of this, e.g. allow ''%%=>%%'' but not ''fn''.
  
 +===== Changelog =====
 +
 +  * 2019-03-14: Clarify $this binding and explain why we're sticking with always-bind behavior.
 +  * 2019-03-14: Mention ''%%->%%'', ''%%-->%%'', ''_()'' and ''\$x => $x''.
rfc/arrow_functions_v2.txt · Last modified: 2020/08/01 23:53 by carusogabriel