Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126745 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id C54C91A00BC for ; Thu, 13 Mar 2025 23:27:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741908315; bh=wB76hHxy3yKy9qPXT18gms5L6kzVOPfTBiIHzG23Yc0=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=JAajMj8+8mUlPklB8TWeljsl9n10wtXU+ZWkmCnnejrzVpbEUY+XlYWQh9BKG2Ct/ dqR0P/npg8e3dEi8rJcXlb8afi3Sav/nyebAL1Zce1r9wxfJB/cnE4V3WAw5ut6Lm9 zvpKNDtnmBZA3aZcP0nEsncsuTL6R9gcjMFsOnN/1B7qiXPdTT0GmIfu/fHCTSPSbs 82MTEdplWNxmHMmyTVIYe9jSlRP6X+iivoNYVB7q4nhJru3G9kDLrPW7+8UB2FihFU XHF4oUUZH893bGTmDdcQtwUEWYCd9e5BfnwafrNSZFS3B8o3BAn/C7uubqyIih7/IS ArSqPYAXXCPYw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id E61811801E3 for ; Thu, 13 Mar 2025 23:25:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-a8-smtp.messagingengine.com (fhigh-a8-smtp.messagingengine.com [103.168.172.159]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 13 Mar 2025 23:25:13 +0000 (UTC) Received: from phl-compute-11.internal (phl-compute-11.phl.internal [10.202.2.51]) by mailfhigh.phl.internal (Postfix) with ESMTP id 39126114012E; Thu, 13 Mar 2025 19:27:46 -0400 (EDT) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-11.internal (MEProxy); Thu, 13 Mar 2025 19:27:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:cc:content-type:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1741908466; x= 1741994866; bh=5SljliGOQok7WNJeauBbOHPHazc8MASK3B0O6+U+Xmk=; b=q rGX7U80OuCDATCuUu4bfjpqLaMP0IcOEPj7s9eeE/O+/iHJ9mFk06cKxtKxnQrsh M0gyLAnV3TjyXDN2+3lRTtJSMldKx0ZhMqqdb+lxSQqXj98HGMpwAXoT/RTG3wQ/ LPmbykpFso+tQ83PeuaZLB3ZD1MFKz6KmBtUR9is8Cv9E52xreWDvnHL+Y+YLdJK Emo2VMIhQA6ImWF+rJgv/8ayJmjpDCFTxjXU9FLVpZBR8XhRWrmy3eN310g/XjGs RJ3h1hWPYVxS7EdgW5Zmxx40Te6T1okdGIlj0q4UyxqQxyBzJWXfq7D5nlvSpJRz njiiibP2JlDwR4ylunpuw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc: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:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1741908466; x=1741994866; bh=5SljliGOQok7WNJeauBbOHPHazc8MASK3B0 O6+U+Xmk=; b=uAcaYBvmZi2o1eYpOTsf4jjEt7LxCJK+NPCwOK+Rzas8rsJoi4E t0KJFHbnifEYFc3JovykjxKbBdsV7YMHI+odXLrmO+tfPtJ4//6yULj6ZnIljghw srTJC1ks9j+Im3laPtveNoNVHRyAiOkN0T/QTc3SGlaYMegfv96Uw6GcBrpwTyT8 oNurpcH6uH9zPK/exWCNOZHwoPZRzJvfLaZGAM37bOOsdzfl1Aywg96sBbPKNghv HpYamCZDnWDrLGSU8k6tVsd0tJh0+9rYMMqWjOhwrFpTQXcrrzfXeDbFsYegj4hJ oqKz0C/DrlXdIEAaNtuz1/TdJGSb4f0hQHA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdduvdelvdejucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih gvnhhtshculddquddttddmnecujfgurhepofggfffhvfevkfgjfhfutgesrgdtreerredt jeenucfhrhhomhepfdftohgsucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurd gtohguvghsqeenucggtffrrghtthgvrhhnpeffgeevveegtdffgfffvdfftddvheeuleeg veekteffueeliedtgeekjeettdetkeenucffohhmrghinhepphhhphdrnhgvthenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehrohgssegsohht thhlvggurdgtohguvghspdhnsggprhgtphhtthhopeefpdhmohguvgepshhmthhpohhuth dprhgtphhtthhopehtihhmsegsrghsthgvlhhsthhurdgsvgdprhgtphhtthhopegsohgs figvihelsehhohhtmhgrihhlrdgtohhmpdhrtghpthhtohepihhnthgvrhhnrghlsheslh hishhtshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id C91E7780068; Thu, 13 Mar 2025 19:27:45 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Fri, 14 Mar 2025 00:26:03 +0100 To: "Bob Weinand" Cc: internals@lists.php.net, =?UTF-8?Q?Tim_D=C3=BCsterhus?= Message-ID: <44ccdbea-747d-46ca-97f9-8dd63fe8b55a@app.fastmail.com> In-Reply-To: References: <2935d0e2-ddc4-447c-ab37-c9b7337b8b60@app.fastmail.com> <0d94bf183543ee9948fcd31337198438@bastelstu.be> Subject: Re: [PHP-DEV] Re: RFC: short and inner classes Content-Type: multipart/alternative; boundary=34be739e28bc46b19a36711ca385a78b From: rob@bottled.codes ("Rob Landers") --34be739e28bc46b19a36711ca385a78b Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Thu, Mar 13, 2025, at 23:26, Bob Weinand wrote: > Hey Rob, >=20 > On 13.3.2025 21:46:49, Rob Landers wrote: >> On Thu, Mar 13, 2025, at 12:01, Tim D=C3=BCsterhus wrote: >>> Hi >>>=20 >>> Am 2025-03-12 11:10, schrieb Rob Landers: >>> > - Accessing inner classes is done via a new token: ":>" instead of=20 >>> > "::". >>>=20 >>> I don't particularly like that. It is =E2=80=9Cinvented syntax=E2=80= =9D and I don't=20 >>> think that inner classes are sufficiently valuable to dedicate an en= tire=20 >>> operator to them that could serve a more useful purpose in the futur= e.=20 >>> It also got 4 negative points in the rating back when the namespace=20 >>> separator was decided: https://wiki.php.net/rfc/namespaceseparator >>>=20 >>> Would `\\` (i.e. two backslashes) work? The outer class for inner=20 >>> classes effectively act as a namespace, so it makes sense to me to u= se=20 >>> syntax that is similar to namespaces. >>>=20 >>> I'll look into the rest when there is a new implementation, since I=20 >>> assume some details will still be clarified and fixed as part of=20 >>> implementing the proposal. >>>=20 >>> Best regards >>> Tim D=C3=BCsterhus >>>=20 >>=20 >> I am not particularly attached to the separator. I specifically chose= it due to being a mixture of :: and -> and -: seemed like a bad idea. I= n other words, an inner class felt natural to use :> -- however, I have = some issues with it myself. Particularly, it is too much like |> and as = shown in the namespace RFC, way too easy to typo. Personally, after usin= g it for a few days, I'd almost rather go back to :: ... >>=20 >> I will give \\ a try, but it has to be typed quite a bit when referen= cing inner classes, so keeping it easy to type is a must. I feel like \\= requires a large movement to type, at least on a qwerty non-english key= board. Maybe people using other keyboards can chime in. > Please go back to ::. The double colon was perfectly fine, the only th= ing which was weird was the implicit constant. It's fine for constants a= nd inner classes to share the same name scoping (i.e. a constant must no= t share a name with an inner class). But an inner class should not be an= actual constant. >=20 > But otherwise, this was perfectly fine. >=20 My biggest issue with `::` is that it gets weird: class Foo { public class Bar {} public const Bar =3D ""; public static function Bar() {} } echo Foo::Bar; // this is the constant new Foo::Bar(); // this is the class Foo::Bar(); // this is the method new (Foo::Bar()); // this is the method new (Foo::Bar); // this is constant I can now differentiate between these all in the AST, but it seems weird= to me. If we go this route, I'd personally have the preference to allow= them all and let people's code-style dictate what is acceptable or not = -- assuming I can ensure there is no ambiguity in the grammar. At least = with `:>` (or something else) we don't have to even have that discussion= . :) >>> I don't think that inner classes are sufficiently valuable >>=20 >> I'm curious why some people feel this way and why some other people a= re saying the opposite (emphatically). I'll nudge the private emails I'v= e received to speak up publicly on the list as well. But, why do you fee= l this way? >=20 > I don't know why some people feel this way, but at least with the auto= loading mechanisms we have in PHP there are definite limitations to mult= iple classes in one file: > - If you deserialize your data structure and it contains another class= , whose name does not match the file name, you better hope to god that i= t has been autoloaded already. Surprising failures in production follow.= (e.g.: the amphp\parallel process runner will try to serialize your exc= eption. That's fine. But as soon as it's accidentally bubbling up and as= it's not autoloadable, the hell breaks loose.) > - Enums or Data Transfer objects specific to one or multiple functions= of only this specific class would naturally fit into the same file. But= you can't do it ... because the autoloading might try to load the enum = first, before the class whose constructor or function you want to call i= s actually loaded. > - Now, if you actually stuff multiple classes / enums into a single fi= le, it's non-trivial to figure out (as the human reader, but obviously f= or the autoloader too) which file to access to read up the definition of= a specific enum (short of using dedicated tooling for it). >=20 >=20 > Certainly, one may say - yeah, just religiously use different files fo= r ... every ... single ... class. > But what's the point of that dogma? > It definitely doesn't help the organization of dedicated helper struct= ures tied to a single class. > It's a tool for organization. It's not complex to understand. >=20 > Outside of very puristic arguments I don't see any reason why one woul= d not want inner classes. >=20 >=20 > Further, with short classes, should they hopefully be introduced as we= ll, it will become trivial to write shapes for any internal datastructur= es - simply using a "class Point(int $x, int $y); private Point $pos;" r= ather than "/** @var list{int, int} */ private array $pos;". > This will be a very ergonomic way to reduce ad-hoc arrays which are on= ly typehinted by phpdoc, giving proper typing and also safe access to st= ructures via named accessors rather than [0] and [1] etc. >=20 > Further Questions on the (original) RFC: >=20 > - Why is there a conflict in static properties and the inner class nam= e? The former always has a leading $ sigil. >=20 Funny enough, this was due to me messing up the AST such that it was try= ing to access a property instead of a constant. Once I fixed that, the c= onflict went away. > - Any particular reason to disallow abstract inner classes? Feels arbi= trary. >=20 This went away as well, once I started cleaning up the grammar. Basicall= y, I couldn't work out how to allow `::` in `extends`. I eventually figu= red it out once I implemented `:>`. Replacing `:>` with virtually anythi= ng else is quite possible -- including going back to `::` (I think). > And a note: I consider the inheritance example misguided as "static co= nstructors" (static methods which invoke new()) would be a better patter= n here. Could you maybe come up with another example here? >=20 >=20 >=20 > Bob >=20 That was a pretty bad example! It illustrated the point but would probab= ly be a bad practice.=20 =E2=80=94 Rob --34be739e28bc46b19a36711ca385a78b Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


On Thu, Mar 13, 2025, at 23:26, Bob Weinand wrote:
=

Hey Rob,

=
On 13.3.2025 21:46:49, Rob Landers=0A = wrote:
On Thu, Mar 13, 2025, at = 12:01, Tim D=C3=BCsterhus wrote:
Hi

Am 2025-03-12 11= :10, schrieb Rob Landers:
> - Accessing inner classes i= s done via a new token:=0A ":>" instead of 
> "::".

I don't particularly like tha= t. It is =E2=80=9Cinvented syntax=E2=80=9D and=0A I don't =
think that inner classes are sufficiently valuable to=0A = dedicate an entire 
operator to them that co= uld serve a more useful purpose in=0A the future. 
It also got 4 negative points in the rating back when the=0A = namespace 
<= br>
Would `\\` (i.e. two backslashes) work? The outer class for= =0A inner 
classes effectively act as a name= space, so it makes sense=0A to me to use 
sy= ntax that is similar to namespaces.

I'll lo= ok into the rest when there is a new implementation,=0A since I=  
assume some details will still be clarified and fix= ed as=0A part of 
implementing the proposal.=

Best regards
Tim D=C3=BCster= hus


I am not pa= rticularly attached to the separator. I=0A specifically chose it = due to being a mixture of :: and -> and=0A -: seemed like a ba= d idea. In other words, an inner class felt=0A natural to use :&g= t; -- however, I have some issues with it=0A myself. Particularly= , it is too much like |> and as shown in=0A the namespace RFC,= way too easy to typo. Personally, after using=0A it for a few da= ys, I'd almost rather go back to :: ...

I w= ill give \\ a try, but it has to be typed quite a bit when=0A ref= erencing inner classes, so keeping it easy to type is a must.=0A = I feel like \\ requires a large movement to type, at least on a=0A = qwerty non-english keyboard. Maybe people using other keyboards=0A = can chime in.

Please go back to ::. The dou= ble colon was perfectly fine, the=0A only thing which was weird was= the implicit constant. It's fine=0A for constants and inner classe= s to share the same name scoping=0A (i.e. a constant must not share= a name with an inner class). But=0A an inner class should not be a= n actual constant.

But otherwise, this was perfectly fine.
=


My biggest issue with `::` is that = it gets weird:

class Foo {
&n= bsp; public class Bar {}
  public const Bar =3D "";
  public static function Bar() {}
}
<= /div>

echo Foo::Bar; // this is the constant
new Foo::Bar(); // this is the class
Foo::Bar(); // = this is the method
new (Foo::Bar()); // this is the method=
new (Foo::Bar); // this is constant

<= div>I can now differentiate between these all in the AST, but it seems w= eird to me. If we go this route, I'd personally have the preference to a= llow them all and let people's code-style dictate what is acceptable or = not -- assuming I can ensure there is no ambiguity in the grammar. At le= ast with `:>` (or something else) we don't have to even have that dis= cussion. :)

I don't think that inner classes are sufficiently va= luable

I'm curious why some pe= ople feel this way and why some other=0A people are saying the op= posite (emphatically). I'll nudge the=0A private emails I've rece= ived to speak up publicly on the list as=0A well. But, why do you= feel this way?

I don't know why some = people feel this way, but at least with the=0A autoloading mechanis= ms we have in PHP there are definite=0A limitations to multiple cla= sses in one file:
- If you deserialize your data structur= e and it contains another=0A class, whose name does not match the f= ile name, you better hope to=0A god that it has been autoloaded alr= eady. Surprising failures in=0A production follow. (e.g.: the amphp= \parallel process runner will=0A try to serialize your exception. T= hat's fine. But as soon as it's=0A accidentally bubbling up and as = it's not autoloadable, the hell=0A breaks loose.)
- = Enums or Data Transfer objects specific to one or multiple=0A funct= ions of only this specific class would naturally fit into the=0A sa= me file. But you can't do it ... because the autoloading might=0A t= ry to load the enum first, before the class whose constructor or=0A = function you want to call is actually loaded.
- Now, if = you actually stuff multiple classes / enums into a=0A single file, = it's non-trivial to figure out (as the human reader,=0A but obvious= ly for the autoloader too) which file to access to read=0A up the d= efinition of a specific enum (short of using dedicated=0A tooling f= or it).

Certainly, one may say - yeah, just = religiously use different=0A files for ... every ... single ... cla= ss.
But what's the point of that dogma?
It= definitely doesn't help the organization of dedicated helper=0A st= ructures tied to a single class.
It's a tool for organiza= tion. It's not complex to understand.

Outside of very= puristic arguments I don't see any reason why one=0A would not wan= t inner classes.

Further, with short classes, should = they hopefully be introduced=0A as well, it will become trivial to = write shapes for any internal=0A datastructures - simply using a "c= lass Point(int $x, int $y);=0A private Point $pos;" rather than "/*= * @var list{int, int} */=0A private array $pos;".
Th= is will be a very ergonomic way to reduce ad-hoc arrays which=0A ar= e only typehinted by phpdoc, giving proper typing and also safe=0A = access to structures via named accessors rather than [0] and [1]=0A = etc.

Further Questions on the (original) RFC:

- Why is there a conflict in static properties and the inner=0A = class name? The former always has a leading $ sigil.


Funny enough, this was due to me messing up the AS= T such that it was trying to access a property instead of a constant. On= ce I fixed that, the conflict went away.

- Any particular reason to disall= ow abstract inner classes? Feels=0A arbitrary.

=

This went away as well, once I started cleaning up t= he grammar. Basically, I couldn't work out how to allow `::` in `extends= `. I eventually figured it out once I implemented `:>`. Replacing `:&= gt;` with virtually anything else is quite possible -- including going b= ack to `::` (I think).

And a note: I consider the inheritance example = misguided as=0A "static constructors" (static methods which invoke = new()) would be=0A a better pattern here. Could you maybe come up w= ith another=0A example here?


Bob


That was a pretty bad example! It illustrated= the point but would probably be a bad practice. 

=E2=80=94 Rob
--34be739e28bc46b19a36711ca385a78b--