Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125460 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 BCD971A00BD for ; Fri, 6 Sep 2024 23:28:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1725665413; bh=b5EBE2iByHQr2Jkq6V2qemeF0gtcLYBqtMCweXwMDuc=; h=Date:From:To:In-Reply-To:References:Subject:From; b=eUuufhQM1SOwLPgiwqQfo4wiqGU15Mv81zhtjzmzGOXywu0BV+R9gnpHNFpFxtYwj SkLJ2u9caaRpM9v46Htx1QpzuInsxgMHevALqs31LIN50QJJJi6mpBaEaM42Pp4UAT 4onT1RGO+f0JOLIqiJknC8bCJz0jazhrIYkk4vKy6Wd5MHyk9GIR4RXCOU/4GznZ6F lntZwtyi1kPcA9ZkhpVIjbTGUmuGaugVlOSY6asGTy4mk1eprrUIDnyJAciCPa8ocn 4WrhMwQ32EAneaVjcBMW7Ce5gxeagOb4MTjFF+eSTXEPMMCme3zLsIKIGI9689cDAL yJmifEhDpZwLA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4E45718006D for ; Fri, 6 Sep 2024 23:30:12 +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=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fout8-smtp.messagingengine.com (fout8-smtp.messagingengine.com [103.168.172.151]) (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 ; Fri, 6 Sep 2024 23:30:11 +0000 (UTC) Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 1B91D13801CB for ; Fri, 6 Sep 2024 19:28:12 -0400 (EDT) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-01.internal (MEProxy); Fri, 06 Sep 2024 19:28:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=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=1725665292; x=1725751692; bh=p40sxIi6Vb UqHelsAG7gZrnxrQU2AVz10kL0llRRuKY=; b=XpQi1+S4vUvBNcsESfBtruetoz ZCnug1p5LJ8tMKtNIJ0OmNNDo8pTHhqIIF7qdQ5KxJur+ZkniftCRIDwr2xPHRXo FQB4Fwh529QQy1klriXQUuS+Jm5PDlmH/zdiMZ96Npgv/c8GjjAqAEMrcNBB0/X3 /NmzLhNdwjbwDTPN7qQQVX/smkvEbzcby7FLFRX9rGcUhJcmmMGpCqug7K+3IS9o K9b+9xW5jEN2LYtfZVWkTR7urj7ixVnt/RaeGB/nxZ08z9ochbzCmVR0lPnA2NuG a1P/qMX0WxJSWLLP2uK+i1OO3Cf6+BlqWL6T/L1UDYwWGLbukDR0XQWOntoA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=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-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; t=1725665292; x=1725751692; bh=p40sxIi6VbUqHelsAG7gZrnxrQU2 AVz10kL0llRRuKY=; b=QrSnU1IZPDA1wHR2ojWZ+Ts3LuAlw3oey5H+V5FU3GJ6 SXc/tyJ7h1HooFdmoEqo5B2qRhmn16TKEGXzXDCol2Y55ygJ9pKpKtueWsCDB2oA XVurcfv2PEjY3bSkb8i1PgeAv0G5eZIv1xVN+wp42PsNb8RjmtuMZg45+df97hud 4eQqCUEKxJvriOC7PPqFh3E6qspcF9zrJddG7Guifv2TjWjGbj8cjVaYcLV0Bg3y UPC34P9sO7sw71eVYRTKnm5bAkVhtMxk9H/1ikmpneXYSQzS2xSM4nmwL2RJM2H5 gvbDOiRpO4prOKoeX7xOJYFDFtKKaZchg3q+8HJBSg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrudeivddgvddvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucgoufhushhpvggtthffoh hmrghinhculdegledmnecujfgurhepofggfffhvffkjghfufgtsegrtderreertdejnecu hfhrohhmpedftfhosgcunfgrnhguvghrshdfuceorhhosgessghothhtlhgvugdrtghoug gvsheqnecuggftrfgrthhtvghrnheptdeitddvvdevhfdufffhgeelffetgeffveekheek feeluedutdeiveekvdetjedvnecuffhomhgrihhnpeefvheglhdrohhrghenucevlhhush htvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehrohgssegsohhtthhl vggurdgtohguvghspdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuthdprh gtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id ABA76780067; Fri, 6 Sep 2024 19:28:11 -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: Sat, 07 Sep 2024 01:27:47 +0200 To: internals@lists.php.net Message-ID: In-Reply-To: References: <0fa39535-f22d-4eba-b4df-90abe39e683a@app.fastmail.com> Subject: Re: [PHP-DEV] bikeshed: Typed Aliases Content-Type: multipart/alternative; boundary=0ec32c13434c4e64ac0d17a3a7eab4e8 From: rob@bottled.codes ("Rob Landers") --0ec32c13434c4e64ac0d17a3a7eab4e8 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Fri, Sep 6, 2024, at 22:45, Larry Garfield wrote: > Hi Rob. >=20 > First of all, I'm very much in favor of type aliases generally, so tha= nk you for taking a swing at this. >=20 > Second, it looks like you've run into the main design issue that has a= lways prevented them in the past: Should aliases be file-local and thus = not reusable, or global and thus we need to figure out autoloading for t= hem? It looks like your answer to that question at the moment is "yes".= :-) While I can see the appeal, I don't think that's the best approach= . Or rather, if we go that route, they shouldn't be quite so similar sy= ntactically. >=20 > There seems to be two different implementations living in the same RFC= , uncomfortably. In one, it's a compiler-time replacement. In the othe= r, it's a special class-like. But the RFC seems to go back and forth on= what happens in which case, and I'm not sure which is which. >=20 > However, you have demonstrated a working class-like for it, which is f= rankly the biggest hurdle. So I think the direction has promise, but sh= ould be adjusted to go all-in on that approach. >=20 > To wit: >=20 > typealias Stringy: string|Stringable; > typealias UserID: Int; > typealias TIme: Hour|Minute|Second; > typealias FilterCallback: callable(mixed $a): bool; (eventually...) >=20 > (etc.) >=20 > Each of those produces a class-like, which can therefore be autoloaded= like a class. The syntax is also a bit closer to a class (or an Enum, = I suppose), so it's much more self-evident that they are defining a reus= able thing (whereas "use" does not do that currently). And the syntax i= s not stringy, like the proposed type_alias(), so it's easier to write. = I wouldn't even include type_alias() at that point. It exists at runti= me, so reflection is meaningful. >=20 > Aliases can then be used only in parameter, return, property, and inst= anceof types. Extends and implements are out of scope entirely. >=20 > (Whether the keyword is typealias or typedef, uses : or =3D, or whatev= er, is its own bikeshed I won't dive into at the moment.) >=20 > Then, as a separate, entirely optional, maybe even separate RFC (or se= cond vote, or whatever), we have a `use string|Stringable as Stringy` sy= ntax. Like all other `use` declarations, these are compile-time only, s= ingle-file only, and do not exist at runtime, so no reflection. They co= mpile away just like all other use-statements now. >=20 > I'm not personally convinced the second is really necessary if we do a= good enough job on the first, but I'd probably not stand in the way of = having both. That's a really good point and would clear up quite a bit of confusion a= nd complexity. >=20 > Having typealias/typedef as a class-like also opens up some interestin= g potential in the future, because classes have all sorts of other thing= s they do, but that is probably too complex scope creepy to get into her= e so I will not go further than that mention. >=20 > I suspect there's also other edge case bits to worry about, particular= ly if trying to combine a complex alias with a complex type, which could= lead to violating the DNF rule. For example: Oh, DNF is the bane of my existence with this RFC=E2=80=94I don't want t= o mess this up. I'll see you at the end of the example, though. >=20 > typealias Foo: (Bar&Baz)|Beep; >=20 > use (Bar&Baz)|Beep as Foo; >=20 > function narf(Foo&Stringable $s) {} >=20 > With the compile time approach, that would expand to `(Bar&Baz)|Beep&S= tringable`, which is not a valid type def. I can see how you arrived at this, but I think you may have missed a ste= p, since the entirety of Foo will be &'d with Stringable. Foo =3D (Bar & Baz) | Beep want: (Foo) & Stringable expand Foo: ((Bar & Baz) | Beep) & Stringable Which can be reduced to the following in proper DNF (at least, it compil= es=E2=80=94https://3v4l.org/0bMlP): (Beep & Stringable) | (Bar & Baz & Stringable) It's probably a good idea to update the RFC explaining how expansion wor= ks. >=20 > With the runtime approach, I don't know if that could be handled grace= fully or if it would still cause an error. >=20 > I'm not sure what the right solution is on this one, just pointing it = out as a thing to resolve. >=20 > --Larry Garfield >=20 =E2=80=94 Rob --0ec32c13434c4e64ac0d17a3a7eab4e8 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
On Fri, Sep 6, = 2024, at 22:45, Larry Garfield wrote:
Hi Rob.

First of= all, I'm very much in favor of type aliases generally, so thank you for= taking a swing at this.

Second, it looks l= ike you've run into the main design issue that has always prevented them= in the past: Should aliases be file-local and thus not reusable, or glo= bal and thus we need to figure out autoloading for them?  It looks = like your answer to that question at the moment is "yes". :-)  Whil= e I can see the appeal, I don't think that's the best approach.  Or= rather, if we go that route, they shouldn't be quite so similar syntact= ically.

There seems to be two different imp= lementations living in the same RFC, uncomfortably.  In one, it's a= compiler-time replacement.  In the other, it's a special class-lik= e.  But the RFC seems to go back and forth on what happens in which= case, and I'm not sure which is which.

How= ever, you have demonstrated a working class-like for it, which is frankl= y the biggest hurdle.  So I think the direction has promise, but sh= ould be adjusted to go all-in on that approach.

=
To wit:

typealias Stringy: string|Stri= ngable;
typealias UserID: Int;
typealias TIm= e: Hour|Minute|Second;
typealias FilterCallback: callable(= mixed $a): bool;  (eventually...)

(etc= .)

Each of those produces a class-like, whi= ch can therefore be autoloaded like a class.  The syntax is also a = bit closer to a class (or an Enum, I suppose), so it's much more self-ev= ident that they are defining a reusable thing (whereas "use" does not do= that currently).  And the syntax is not stringy, like the proposed= type_alias(), so it's easier to write.  I wouldn't even include ty= pe_alias() at that point.  It exists at runtime, so reflection is m= eaningful.

Aliases can then be used only in= parameter, return, property, and instanceof types.  Extends and im= plements are out of scope entirely.

(Whethe= r the keyword is typealias or typedef, uses : or =3D, or whatever, is it= s own bikeshed I won't dive into at the moment.)

Then, as a separate, entirely optional, maybe even separate RFC (o= r second vote, or whatever), we have a `use string|Stringable as Stringy= ` syntax.  Like all other `use` declarations, these are compile-tim= e only, single-file only, and do not exist at runtime, so no reflection.=   They compile away just like all other use-statements now.

I'm not personally convinced the second is really = necessary if we do a good enough job on the first, but I'd probably not = stand in the way of having both.

That's a really good point and would clear up quite a bit of confusio= n and complexity.


Having typealias/typedef as a class-= like also opens up some interesting potential in the future, because cla= sses have all sorts of other things they do, but that is probably too co= mplex scope creepy to get into here so I will not go further than that m= ention.

I suspect there's also other edge c= ase bits to worry about, particularly if trying to combine a complex ali= as with a complex type, which could lead to violating the DNF rule. = ; For example:

Oh, DNF is the = bane of my existence with this RFC=E2=80=94I don't want to mess this up.= I'll see you at the end of the example, though.


type= alias Foo: (Bar&Baz)|Beep;

use (Bar&= ;Baz)|Beep as Foo;

function narf(Foo&St= ringable $s) {}

With the compile time appro= ach, that would expand to `(Bar&Baz)|Beep&Stringable`, which is = not a valid type def.

I can se= e how you arrived at this, but I think you may have missed a step, since= the entirety of Foo will be &'d with Stringable.

=
Foo =3D (Bar & Baz) | Beep

w= ant: (Foo) & Stringable

expand Foo: ((B= ar & Baz) | Beep) & Stringable

Whic= h can be reduced to the following in proper DNF (at least, it compiles=E2= =80=94https://3v4l.org/0bMlP):

(Beep & Stringable) | (Bar & Baz &= ; Stringable)

It's probably a good idea to = update the RFC explaining how expansion works.

<= blockquote type=3D"cite" id=3D"qt" style=3D"">

With t= he runtime approach, I don't know if that could be handled gracefully or= if it would still cause an error.

I'm not = sure what the right solution is on this one, just pointing it out as a t= hing to resolve.

--Larry Garfield
=


=E2=80= =94 Rob
--0ec32c13434c4e64ac0d17a3a7eab4e8--