On Tue, Mar 14, 2023, at 3:41 PM, Rowan Tommins wrote:
> Hi all,
>
> I have been pondering for a while how to improve the anonymous class
> syntax to allow "capturing" of values from the outer scope, and came up
> with the idea of a special variable marker for "lexically captured
> variable" - instead of $foo, you would write $!foo or $^foo (I quite
> like the "upwardness" of $^).
>
> To give a simple example, values can only pass into the anonymous class
> via its constructor, like this:
>
> function foo(int $outer) {
> return new class($outer) {
> public function __construct(
> private int $myProp
> ) {}
> public function getIt() {
> return $this->myProp;
> }
> };
> }
>
> The idea is that you would instead be able to reference an outer
> variable directly anywhere in the declaration, removing a lot of
> boilerplate:
>
> function foo(int $outer) {
> return new class {
> public function getIt() {
> return $^outer;
> }
> };
> }
>
> The outer variable would be captured by value, and carried around with
> the instance, like existing closures.
>
> I suggest it is also treated as readonly, and visible strictly in the
> lexical definition, not generally in private scope (it couldn't be
> referenced from an applied trait, for instance).
>
> Using it to initialise a property or local variable would allow you to
> give it an explicit scope, while still avoiding the constructor:
>
> function foo(int $outer) {
> private $inner = $!outer;
> return new class {
> public function getIt() {
> $this->inner++;
> return $this->inner;
> }
> };
> }
>
>
> It then occurred to me that the same syntax could be used in
> multi-statement anonymous functions instead of an explicit use()
> statement. This strikes a different balance between conciseness and
> explicitness than full automatic capture:
>
> $before = function($x) use ($y, $z) {
> $a = $x * $y;
> return do_something($a, $z);
> }
> $after = function($x) {
> $a = $x * $^y;
> return do_something($a, $^z);
> }
>
>
> To keep this message short, I've put some more examples and thoughts
> into a GitHub Gist here:
> https://gist.github.com/IMSoP/4157af05c79b3df4c4853f5a58766341
>
> I'd be interested to hear anyone's thoughts - is this a promising idea
> to explore, or have I gone completely off the rails?
Pourque no los dos?
Ilija's point about implementation challenges concerns me, but my initial
thought is that I quite like it. I've run into the same issue with capturing
into anon classes and wished for something like this.
As you were describing it, I was also thinking of the potential implications
for closures, too. That sounds... kinda fun. :-) However, I agree with Ilija
that the original proposal to just do it automatically would be better; and if
that didn't pass, I have no expectation that an alternate with a funky new
syntax would do any better.
The other concern is that this introduces a whole new realm of possible
behaviors; like, what does $^foo mean in a non-anon-class context? Does it?
Could it be made to mean something in the future? Does it become an alternate
syntax for `global`? What else could we do with it? This rabbit hole goes
very deep very quickly, and pursuing this for anon classes without considering
the longer-term implications seems both impossible (because people will ask)
and unwise.
--Larry Garfield
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php