Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119697 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 35296 invoked from network); 14 Mar 2023 21:23:58 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 14 Mar 2023 21:23:58 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8EEF4180545 for ; Tue, 14 Mar 2023 14:23:57 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (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 14:23:56 -0700 (PDT) Received: by mail-pl1-f176.google.com with SMTP id ix20so11500420plb.3 for ; Tue, 14 Mar 2023 14:23:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1678829036; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=OzIjbsDbclvetILsZRVK4BSLZXjbSF7q93L21PTwWv0=; b=kxTpdYFdVo90FQrISpEiORaoLDAX9m2AwviJLrFLp1VmOhl6Kp0Ahn12uSsiiYx/I5 Z3IEpQSkYDihxoFYn6+GIAKXOUkZfxXVdklAZ3gdIhnAxe/WRybIkicerhT0RVEIGw8H RvkH37j/U1V0w1TWID+tjuGiJrrb7a5Y8Lkf5B3ug0OsRR7AOvpolfQL20qnrmGy9AwX W8U3p8fLZ6P9YrRg3eBPnV/ZzsPYzGf3rRyeQrZqe5Xc2RWKhCa3cVuXrTuWD7LlpEQn g/ogI8pz4mCNoO1a0sh3ssdTwCrG7Zn+iIJr4EXxFCah7tB/jtzJMpqu4LgQ2V/Zc1Eq 9xmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678829036; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OzIjbsDbclvetILsZRVK4BSLZXjbSF7q93L21PTwWv0=; b=pPpjxiaxO1lXsaXb4cmSfE3/XCGMMwSyURKtZa3Cg6EeM3fXa2hT4LytQdsB4x3h+0 ASprsgudJgnriatq6a3FaW54klGiYIfGkTMuQnGT0tgyNCG+lnqTm3aUf1FSjnJSP0Jv cqWCmOSAloZK4fInVDU7ZfRsq2PJ0Bwj7jQLOF2dfjsvoASCtHVYzV3dEnM80p30G2Zw FNTE0z8i+XIUBW5TX6oQIr/xhJUELn5OicZkEdTuDfQMAgs/qotLch5ScE25hN+F5Lxd rPhuFGPQdrP+7rqSXiE8mmyHXuTSmNzbHuQPBUEsx7TeCRBFYCFJOUcKJEun6fAGgkYZ ctZA== X-Gm-Message-State: AO0yUKV7YiODWhJWNcSsVpQ8xJ59Si8juGMFYExW3MH2mAddd/5Siw9K DAs3Zrh+ksZbiXalbYKj30ZhtWkj2V7vy/CX7YYoIpq8 X-Google-Smtp-Source: AK7set8v6s3lnNQfYZJbtD4bby0C4HmxLsyJRpOzkcudRCYb2Hdd1S+APxgVbMqBwl8L2Mt3E1YDpLjo4/IGLZoKhTw= X-Received: by 2002:a17:902:f688:b0:19f:3cc1:e3bd with SMTP id l8-20020a170902f68800b0019f3cc1e3bdmr217154plg.4.1678829035527; Tue, 14 Mar 2023 14:23:55 -0700 (PDT) MIME-Version: 1.0 References: <8a9a04b3-45e6-47dd-dee8-0f524e49bd37@gmail.com> In-Reply-To: <8a9a04b3-45e6-47dd-dee8-0f524e49bd37@gmail.com> Date: Tue, 14 Mar 2023 22:23:44 +0100 Message-ID: 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: tovilo.ilija@gmail.com (Ilija Tovilo) Hey Rowan On Tue, Mar 14, 2023 at 9:41=E2=80=AFPM 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; > } > }; > } 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/2OcmP This could be avoided by adding the value to the constructor, but that fully defeats the purpose of your proposal. Holding the value indefinitely would create a leak and also doesn't really work as `createAnonymousClass` could be called multiple times and thus capturing multiple `$value`s. We could also decide to disallow instantiations of anonymous classes in other places, that would probably make most sense. This way the captured value could be attached somewhere in the object and $^foo could access that instead. That being said, I am indeed very skeptical if the added complexity is wort= h it. ``` // Lexical values could be used to initialse private, protected, or public properties // The same lexical value can be used any number of times $x =3D 1; $example =3D new class { private $x =3D $^x; protected $sharedX =3D $^x; public $alsoX =3D $^x; } ``` This could also prove technically challenging. Currently, property defaults are constant ASTs and unique per class (not object). For your case, they would need to be different per instance, which might require quite a bit of refactoring. As for the syntax in closures, that seems a bit more useful to me personally, although I dislike the multi-nesting. Moving code, it might be easy to miss that the number of "^" needs adjustments. I'd personally prefer the previously proposed approach of capturing just by name. Good naming should minimize the risk of clashing variables. Regards, Ilija