PHP RFC: Alternative "use" syntax for Closures
- Version: 0.1
- Date: 2019-06-15
- Author: Wes (@WesNetmo)
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/alternative-closure-use-syntax
Introduction
PHP users often say that they find defining the lexical-scope imports cumbersome, because they hate importing the variables explicitly.
My opinion on the matter is that what's actually annoying is not writing the variable names, but the syntax with which the imports are defined.
In ES we are required to declare variables but we don't find it annoying; in PHP we don't
have to declare variables, but we are required to specify which one we want to import in
Closure
s. It won't be much different if not for the syntax. It is very standard in ES,
but irksome in PHP.
Specifically, it requires a lot of effort to write compared to normal expressions. Whitespace, parentheses, possible indentation on different depths. Also, being in the middle of the signature, it is very invasive, visually, as it separates the arguments from the return information:
public function bar(){ // ... $closure = function ( ArgumentType $argument1, ArgumentType $argument2, ArgumentType $argument3, ArgumentType $argument4 ) use ( // indent out // indent in $importVariable1, &$importVariable2, $importVariable3, &$importVariable4 ): ReturnType { // indent out again // indent in again }; } // or also public function bar(){ // ... $closure = function ( ArgumentType $argument1, ArgumentType $argument2, ArgumentType $argument3, ArgumentType $argument4 ) use ( // indent out // indent in $importVariable1, &$importVariable2, $importVariable3, &$importVariable4 ): ReturnType { // indent out again // indent in again }; }
Proposal
This RFC proposes to provide an alternative syntax for use()
, one resembling
global
or Python's nonlocal
modifier:
$closure = function ( ArgumentType $argument1, ArgumentType $argument2, ArgumentType $argument3, ArgumentType $argument4 ): ReturnType { use $importVariable1, &$importVariable2, $importVariable3, &$importVariable4; // ... }; // or also $closure = function ( ArgumentType $argument1, ArgumentType $argument2, ArgumentType $argument3, ArgumentType $argument4 ): ReturnType { use $importVariable1, &$importVariable2; use $importVariable3, &$importVariable4; // ... };
Unlike global
, which is allowed everywhere in a function body, use
must only
appear at the very top of the Closure
's body. For example, the following code will
cause a syntax error:
$closure = function ( ArgumentType $argument1, ArgumentType $argument2, ArgumentType $argument3, ArgumentType $argument4 ): ReturnType { use $importVariable1, &$importVariable2; // ok echo 123; use $importVariable3, &$importVariable4; // ^ syntax error, as "use" can only be preceded by other "use" statements };
Exactly like the current use()
, variables are imported by value, unless prefixed by
&
. A Closure
can define multiple use;
statements; they can go on multiple
lines and they can be surrounded by whitespace and comments as with most of other
expression statements.
Backward Incompatible Changes
None.
Proposed PHP Version(s)
Next PHP minor version
Proposed Voting Choices
Vote will require 2/3 majority