Re: Brainstorming idea: inline syntax for lexical (captured) variables
| From: | Rowan Tommins | Date: | Tue, 14 Mar 2023 22:44:11 +0000 |
| Subject: | Re: Brainstorming idea: inline syntax for lexical (captured) variables | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-119699@lists.php.net to get a copy of this message | ||
On 14/03/2023 21:23, Ilija Tovilo wrote:
One thing to note is that, as I've learned recently, anonymous classes can actually be instantiated at a later point with some tricks. https://3v4l.org/2OcmPHuh, that's freaky... I guess this is all a reminder that these really are anonymous *classes*, not anonymous *instances* - at some point, a class entry needs to be generated. I guess you'd have to generate a new class entry every time the "new class" line was run, and inject the extra values into that. If it was limited to capturing scalars and arrays, you could treat it as a kind of macro expansion, i.e. this ... $example = new class {
public $inner = $^outer;} ... could be a sort of sugar for: eval(
sprintf(
'return new class {
public $inner = %s;
};',
var_export($outer, true)
)
);
Which is valid code, if not particularly efficient: https://3v4l.org/sQaUS
That doesn't allow for normal object semantics, though, so is probably a non-starter.
This could also prove technically challenging. Currently, property defaults are constant ASTs and unique per class (not object).As I understand it, the main reason object properties weren't included in the "new in initializers" RFC was the problem of when side effects would occur: https://wiki.php.net/rfc/new_in_initializers#unsupported_positions That's not an issue here, because we're not *creating* an object, we're "just" resolving the $^outer token to an existing zval, and storing it in the default property table. It might actually be easier to *only* allow capture into property initialisers: 1. Create a new class entry without any property default (or clone a pre-compiled base) 2. Add the captured values to the default property table 3. Create an instance, run its constructor, etc, as currently Or even: 1. Use the existing logic to create an anonymous class entry ignoring the capturing syntax 2. Create an instance, initialise normal defaults, but don't run the constructor yet 3. Push the captured values directly into the *instance* properties 4. Run the constructor I'm probably in way over my head here, so I should probably stop here, in the hope that it will inspire someone more knowledgeable to come up with something workable, because I'd really love for anonymous classes to be more flexible than they are. Regards, -- Rowan Tommins [IMSoP]