Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:120455 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 36965 invoked from network); 30 May 2023 13:13:59 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 May 2023 13:13:59 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DFAC3180511 for ; Tue, 30 May 2023 06:13:58 -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.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS17378 206.123.64.0/18 X-Spam-Virus: No X-Envelope-From: Received: from mail1.25mail.st (mail1.25mail.st [206.123.115.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 30 May 2023 06:13:58 -0700 (PDT) Received: from smtpclient.apple (unknown [49.48.216.76]) by mail1.25mail.st (Postfix) with ESMTPSA id 90649603CD for ; Tue, 30 May 2023 13:13:55 +0000 (UTC) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3731.600.7\)) Date: Tue, 30 May 2023 20:13:40 +0700 References: <64EAB991-7082-47B8-B546-73CD08243C6E@koalephant.com> To: PHP internals In-Reply-To: Message-ID: <23DF3A9A-9F11-4786-A011-41AE0FA9CFA9@koalephant.com> X-Mailer: Apple Mail (2.3731.600.7) Subject: Re: [PHP-DEV] Declaration-aware attributes From: php-lists@koalephant.com (Stephen Reay) (Resending to the list without all the history because qmail complained = about message size) >>=20 >> Hi Andreas, >>=20 >> I too have wondered (and I think asked in room11?) about such a = concept. >=46rom memory the general response was =E2=80=9Cjust do it in = userland with a wrapper=E2=80=9D so its good to see someone else is = interested in this being part of the language. >>=20 >> While I agree that it=E2=80=99s most useful if the `Reflector` = instance is available in the constructor, I=E2=80=99m not keen on the = proposed magic =E2=80=9Cskipping=E2=80=9D of arguments as you suggest. = It seems way too easy to confuse someone (particularly if the attribute = class itself has reason to be instantiated directly in code) >=20 > Good point! Almost made me change my mind completely. But I already > changed it back :) >=20 > When instantiating in code, the "real" signature would have to be > used, and the reflector argument passed explicitly. That=E2=80=99s kind of my point: it=E2=80=99s not super intuitive why = (or the specifics of how) it=E2=80=99s being skipped when it=E2=80=99s = an attribute, vs when it=E2=80=99s instantiated from code. What if = someone specifies an argument with the same name? If they specify args = without names, can they just use null for that? Etc. > This would be > useful for unit tests that want to replicate the realistic behavior. > Also it guarantees that the code of the attribute class can really > count on this value to not be null, no matter how the class is > instantiated. >=20 >=20 I would expect that whether the Reflector object is required is simply a = matter of whether or not the parameter is nullable. If it=E2=80=99s not nullable, then yes, the explicit instantiation call = will need to supply it at the correct location. If it=E2=80=99s only = required when created from attribute usage, then it would accept null, = and the constructor would have appropriate logic to handle that. >>=20 >> I think a better approach would be to suggest authors put the = parameter at the *end* of the parameter list, so that no =E2=80=98skipping= ' is required when passing arguments without names (or put it where you = like if you=E2=80=99re always using named arguments) >=20 > If I understand correctly, the proposal would technically not change, > we just add a recommendation. Technically, yes =E2=80=9Cmy way=E2=80=9D would work fine with the = proposal you=E2=80=99ve suggested, if I choose to always put the = parameter marked by #[ReflectionContext] last. I=E2=80=99m just concerned about confusing usage if =E2=80=9Cinsert this = parameter anywhere=E2=80=9D is the =E2=80=98recommended=E2=80=99 (i.e. = documented example) way to use this feature. Even with that concern, I still prefer this to most other solutions = mentioned so far, for the same reasons: they=E2=80=99re all some degree = of magic. The only other solution I can think of that=E2=80=99s less =E2=80=9Cmagic=E2= =80=9D and more explicit, is (and I have no idea if this is even = feasible technically) to introduce a builtin trait for attribute classes = to use, providing a protected method or property that gives access to = the Reflector (how the trait has access is not really important, I = assume it can be assigned to the object somehow before the constructor = is called). I guess this could also be an abstract class, but a trait = makes it much easier to adopt so that would be my preferred approach. So something like trait AttributeReflector { protected function getReflector(): \Reflector { // do internal stuff } } #[Attribute] class Foo { Use \AttributeReflector; public readonly string $name; function __construct(?string $name =3D null) { $this->name =3D $name ?? $this->getReflector()->name; } }