Re: Brainstorming idea: inline syntax for lexical (captured) variables
| From: | Rowan Tommins | Date: | Thu, 16 Mar 2023 23:05:35 +0000 |
| Subject: | Re: Brainstorming idea: inline syntax for lexical (captured) variables | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-119732@lists.php.net to get a copy of this message | ||
On 16/03/2023 22:14, Larry Garfield wrote:
Wouldn't the functionality described boil down to essentially just materializing into a few extra lines in the constructor? At least to my ignorant non-engine brain it seems straightforward to have this: $a = 1; $b = 2; $c = 3; $o = new class ($a, $b) use ($c) { public function __construct(private int $a, private int $b) {} public function something() {} } Desugar to this: $c = class ($a, $b) use ($c) { private $c; public function __construct(private int $a, private int $b) {Not quite - as Ilija pointed out, the class definition gets compiled once, but the capture needs to happen for every instance, with (potentially) different values of $c. In other words, $c needs to be injected as a constructor argument, not a constant in the class definition. That's still fine, in principle - you can compile to this: $o = class ($a, $b, $c) { public function __construct(private int $a, private int $b, private $c) { } public function something() {} } Or once constructor promotion is de-sugared as well, this: $o = class ($a, $b, $c) { private int $a; private int $b; private $c; public function __construct($a, $b, $c) {$this->c = 3; // By value only, so this should be fine?} public function something() {} }
$this->a = $a; // from constructor promotion
$this->b = $b; // from constructor promotion
$this->c = $c; // from use() statement
// other lines from body of constructor go here
}
public function something() {}
}
It just introduces a lot of extra cases to handle:
* If there's no constructor, create one
* If there is a constructor with other arguments, merge the argument lists; since there will then be an explicit argument list to "new class()", merge those lists as well
* Maybe different handling if those other arguments are already using constructor promotion, as in this example
* If there are existing lines in the constructor body, combine those with the auto-generated assignments
Which is why I'm thinking a first implementation would be reasonable which just took this approach:
* "new class" can either have an argument list or a use() statement, not both
* the use() statement generates a constructor at the top of the class
* if the class body already contains a constructor, the compiler will complain that you have two methods named "__construct"
Regards,
--
Rowan Tommins
[IMSoP]