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