Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119700 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 43595 invoked from network); 14 Mar 2023 22:55:14 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 14 Mar 2023 22:55:14 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D9DC31804F7 for ; Tue, 14 Mar 2023 15:55:12 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,BODY_8BITS, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS19151 66.111.4.0/24 X-Spam-Virus: No X-Envelope-From: Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 14 Mar 2023 15:55:12 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 871305C0884 for ; Tue, 14 Mar 2023 18:55:09 -0400 (EDT) Received: from imap50 ([10.202.2.100]) by compute4.internal (MEProxy); Tue, 14 Mar 2023 18:55:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm2; t=1678834509; x=1678920909; bh=pw6fRKKl7j bta8N/NJ6LnFv7C7hRRCmsBuZdZSz/Nvk=; b=0uKRPLraVrYFtHhUGb6YzL9JG3 YMw90WPOY+F9xzPMOpynfQ6cT+1TjawSgX41TPxbDG/9ojY1a+cKx4qkHlWUeR7g 5kLOSLzLmI2oGdjXxQRpbAM2AS1y92IH+zYDc3KoVWATE63cZuXIwXWilag3+ALh zH5wc7gEnDXqrNuvAK3O71526TVmjAOyJAoV1EJ+l6y5ro3G54435rkgh8uWk43j pV1qXMGCvbDHIgMLxzaDw4lcqjaJ0s6Osav4EpzJ2TqHvY1KHCDANq/ji8ZOEy3r PzTOnldshDcYHxQAwqXOmwEo4Xwe3oCm2MQoFimo6nwyyJAMxFTbRQIqptQw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1678834509; x= 1678920909; bh=pw6fRKKl7jbta8N/NJ6LnFv7C7hRRCmsBuZdZSz/Nvk=; b=R 4R5tHpyy/BkSAWd7P/Wkc7ZwdKL5BIS6lHv3+Ykc4YeGt6cH2Rxtj7sZp4p3SFxd vVe6fHt9ZXI5NHEFeaozXT+xA006PbfanHoC6Xjs2DiqYfDNunG9LUMWGYL7IHeK Gn8q0CsK4O4PmXQ0Sa3GtHRscrMeYYlT4fwoXp8WeszdIRk7ofUBkTr0mYHYnwUx BEnbp9p3x9B1azNqnUECk4xkf+fyiAPBkEmx6Rrg+9Xgl1IGe+MPTpEudzTlO36f 0T6DWYG0zELq9ngFtg3VUh0m869DJgyq/nc+27bZrP7OVkU7BraemzDHwYXEafwH u+bfI8YXDJMLTkuAHvhAA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvddvjedgtddvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvffutgfgsehtqhertderreejnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuggftrfgrthhtvghrnhephfektdffgffhkeeiudehvdehfefgfeehuefgvdel teetkeetgfetjeeiledtleeknecuffhomhgrihhnpehgihhthhhusgdrtghomhenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehlrghrrhihsehg rghrfhhivghlughtvggthhdrtghomh X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 38C171700089; Tue, 14 Mar 2023 18:55:09 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-221-gec32977366-fm-20230306.001-gec329773 Mime-Version: 1.0 Message-ID: In-Reply-To: <8a9a04b3-45e6-47dd-dee8-0f524e49bd37@gmail.com> References: <8a9a04b3-45e6-47dd-dee8-0f524e49bd37@gmail.com> Date: Tue, 14 Mar 2023 17:54:40 -0500 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] Brainstorming idea: inline syntax for lexical (captured) variables From: larry@garfieldtech.com ("Larry Garfield") 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=20 > syntax to allow "capturing" of values from the outer scope, and came u= p=20 > with the idea of a special variable marker for "lexically captured=20 > variable" - instead of $foo, you would write $!foo or $^foo (I quite=20 > like the "upwardness" of $^). > > To give a simple example, values can only pass into the anonymous clas= s=20 > via its constructor, like this: > > function foo(int $outer) { > =C2=A0=C2=A0=C2=A0 return new class($outer) { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 public function __construc= t( > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pr= ivate int $myProp > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ) {} > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 public function getIt() { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re= turn $this->myProp; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } > =C2=A0=C2=A0=C2=A0 }; > } > > The idea is that you would instead be able to reference an outer=20 > variable directly anywhere in the declaration, removing a lot of=20 > boilerplate: > > function foo(int $outer) { > =C2=A0=C2=A0=C2=A0 return new class { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 public function getIt() { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re= turn $^outer; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } > =C2=A0=C2=A0=C2=A0 }; > } > > The outer variable would be captured by value, and carried around with=20 > the instance, like existing closures. > > I suggest it is also treated as readonly, and visible strictly in the=20 > lexical definition, not generally in private scope (it couldn't be=20 > referenced from an applied trait, for instance). > > Using it to initialise a property or local variable would allow you to=20 > give it an explicit scope, while still avoiding the constructor: > > function foo(int $outer) { > =C2=A0=C2=A0=C2=A0 private $inner =3D $!outer; > =C2=A0=C2=A0=C2=A0 return new class { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 public function getIt() { > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 $t= his->inner++; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re= turn $this->inner; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } > =C2=A0=C2=A0=C2=A0 }; > } > > > It then occurred to me that the same syntax could be used in=20 > multi-statement anonymous functions instead of an explicit use()=20 > statement. This strikes a different balance between conciseness and=20 > explicitness than full automatic capture: > > $before =3D function($x) use ($y, $z) { > =C2=A0=C2=A0=C2=A0 $a =3D $x * $y; > =C2=A0=C2=A0=C2=A0 return do_something($a, $z); > } > $after =3D function($x) { > =C2=A0=C2=A0=C2=A0 $a =3D $x * $^y; > =C2=A0=C2=A0=C2=A0 return do_something($a, $^z); > } > > > To keep this message short, I've put some more examples and thoughts=20 > into a GitHub Gist here:=20 > https://gist.github.com/IMSoP/4157af05c79b3df4c4853f5a58766341 > > I'd be interested to hear anyone's thoughts - is this a promising idea=20 > to explore, or have I gone completely off the rails? Pourque no los dos? Ilija's point about implementation challenges concerns me, but my initia= l thought is that I quite like it. I've run into the same issue with ca= pturing into anon classes and wished for something like this. As you were describing it, I was also thinking of the potential implicat= ions 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 alter= nate 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 clas= ses without considering the longer-term implications seems both impossib= le (because people will ask) and unwise. --Larry Garfield