On Thu, 16 Mar 2023 at 09:28, Nicolas Grekas <nicolas.grekas+...@gmail.com> wrote:
> > To overcome the issues spotted in the thread, what about doing some sort > of CPP instead of autocapture? > > new class (...$arguments) use ($outer) extends Foo { > public function getIt() { > return $this->outer; > } > } > > This would be the equivalent of this: > > new class ($outer, ...$arguments) extends Foo { > public function __construct(public mixed $outer, ...$arguments) { > parent::__construct(...$arguments); > } > public function getIt() { > return $this->outer; > } > } > I was actually just thinking about exactly that approach, and wondering it would be possible to do it entirely as an AST rewrite. My only uncertainty so far is what to do with an actual constructor in the class, like this: new class($custom) use ($captured) { public function __construct($custom) { // Duplicate definition error? // Silently renamed and called from the generated constructor? // Merged into the body after the generated lines? } } Forbidding it wouldn't be the worst restriction, but if there was some per-instance setup logic needed, not being able to write a constructor body might be a pain. > And we could also allow this for better type expressivity: > new class (...$arguments) use (private int $outer) extends Foo { > // ... > } > I was going to suggest an "as" clause, similar to traits, which would also allow naming the property differently from the source variable: $foo = 42; $name = 'Bob'; $class = new class use ($foo as private int $counter, $name as readonly string) {} Equivalent to: $foo = 42; $name = 'Bob'; $class = new class($foo, $name) { public function __construct(private int $counter, public readonly string $name) {} } Or in full: $foo = 42; $name = 'Bob'; $class = new class($foo, $name) { private int $counter; public readonly string $name; public function __construct(int $counter, string $name) { $this->counter = $counter; $this->name = $name; } } Regards, -- Rowan Tommins [IMSoP]