Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:125487
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 7EBBA1A00BD
	for <internals@lists.php.net>; Tue, 10 Sep 2024 08:01:06 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
	t=1725955387; bh=jEOIHawxP/ZjjXpEecXGHQjVE6REmLbhyJfH00BSzeA=;
	h=From:Subject:Date:In-Reply-To:Cc:To:References:From;
	b=M7yCowAJ4v2/TnhYig/fxteVs+78mCFPY3Rvm7+DEGD0fjcSzJKzMz1H03HjH59l8
	 PIgXmIW651tf37tDP/xSQJ1OGNrVH9BGcOr53pv2L0v6/V0Hd6vEZSzEVocq+538pH
	 pRd0JXOirhK8MfP2d0gVxgbR9c12WuwCcu9j4ZVmohBRTBdVkLxqRPtxvnOkhVkZ/7
	 8g+n10NJd6Ki/oER+llZmigT00tR3/F30w4Y0urrPspCgioJgYzNBmfUN/I0Bq524Z
	 2ECTKAJo6ZVxo9yarjjl8IM8jaglnbB+SwasmFh6C27PS1+lx03cMbYj1Q1RaLbqKY
	 yvYqdWIf/de4A==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id 796FA180076
	for <internals@lists.php.net>; Tue, 10 Sep 2024 08:03:02 +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.8 required=5.0 tests=BAYES_50,DKIM_SIGNED,
	DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,
	SPF_NONE autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: No
X-Envelope-From: <mike@newclarity.net>
Received: from mail-yw1-f169.google.com (mail-yw1-f169.google.com [209.85.128.169])
	(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 <internals@lists.php.net>; Tue, 10 Sep 2024 08:03:01 +0000 (UTC)
Received: by mail-yw1-f169.google.com with SMTP id 00721157ae682-6c3f1939d12so46003127b3.2
        for <internals@lists.php.net>; Tue, 10 Sep 2024 01:01:00 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=newclarity-net.20230601.gappssmtp.com; s=20230601; t=1725955260; x=1726560060; darn=lists.php.net;
        h=references:to:cc:in-reply-to:date:subject:mime-version:message-id
         :from:from:to:cc:subject:date:message-id:reply-to;
        bh=3t8q2FO7CY5dV1uqZc0Cu16RWTI7jBXOelCC8OaHJk8=;
        b=zkfu5jO1ru/IZna8YKAEGY9qD4gUBw7IfXxMe1oyrjQPjGvR4zkN6VknPPJs4RZFAi
         vuOTZmyjJAJewphMPCKYjGu8PLeEvjIE7gpbN2xIennsrwX27LS4EeRMeFy1N3vVaPnR
         I+m6EJrc4QiSlgR6ftCKw25LZ0vZS3BMcZGJpcrjWOwzv2qUI3c2QAm1w3uEQ/tF2yT/
         L+19OQuCjA0WZA6iDn1iNMy+usnHZF4dH8Soajo4qqb4xXgVqx8BlswigR15GkGC6Iga
         1yFKOP6TylMyyk4fugEGoGTs1tIHfZuiVYsbJHk8NJazznwnlrFQXxOlUBNJagivnFTU
         EDPg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1725955260; x=1726560060;
        h=references:to:cc:in-reply-to:date:subject:mime-version:message-id
         :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
        bh=3t8q2FO7CY5dV1uqZc0Cu16RWTI7jBXOelCC8OaHJk8=;
        b=Q2jOhwRtbCoeQZIfWcfMslk9Ouk9lEaEx5F+48lwzUCEtBWkD2PffmQOBVTLzcvtzC
         QicJWI716vWOWsouaOaRItK+qDk+pMszj17s+OtB0I7MtROQnzdYA+rPZKPlirNh0+my
         Kvt6aJ56qZhLlqKfLOO+0RJOaYXDeH5T59o/FKlL3xLdoSVU67lQET3uLQT7jCX72W5g
         2WprPF5QPCxYrKOg+MaUzprA6r0tgtaSKiOPEFfxwWx//cL673IHGstPm9S4hP5DAk+k
         Xw5r0kFwAufamYXHYPaZ+631KmWX/muo2sA+LOTRoikSvSZoxcRrp0Y0I3gpZNRRLZPB
         488w==
X-Gm-Message-State: AOJu0Yz+8sCfx/fP5hA5yyQsYyAEQ0CZmz6l+CQt3Q6Jbyp5P6lR3R51
	4siEO0ZQNJ9PUzv6+yeF12MeP/Bv0pchcOJrHunAUxvsJ3y7BgJoZ61cqnxqDuoliDiIOPzy4ei
	IsTQ=
X-Google-Smtp-Source: AGHT+IGQXc0o4azc8pvQEG6Cyg3XrvIxHKJebRJBleQosZdaVjxvpkFw8/PJNVflvpCG4gZfxpFrAg==
X-Received: by 2002:a05:690c:4604:b0:6ae:2f25:8bc4 with SMTP id 00721157ae682-6db44f2c242mr117316887b3.16.1725955260100;
        Tue, 10 Sep 2024 01:01:00 -0700 (PDT)
Received: from smtpclient.apple (c-98-252-216-111.hsd1.ga.comcast.net. [98.252.216.111])
        by smtp.gmail.com with ESMTPSA id 00721157ae682-6db96486f1csm2201157b3.58.2024.09.10.01.00.58
        (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
        Tue, 10 Sep 2024 01:00:58 -0700 (PDT)
Message-ID: <50CFF539-AD22-4F89-A65E-77AF76DBD63A@newclarity.net>
Content-Type: multipart/alternative;
	boundary="Apple-Mail=_4DA80B8B-01DD-4204-BCD4-BDABBD30AC7D"
Precedence: bulk
list-help: <mailto:internals+help@lists.php.net
list-unsubscribe: <mailto:internals+unsubscribe@lists.php.net>
list-post: <mailto:internals@lists.php.net>
List-Id: internals.lists.php.net
x-ms-reactions: disallow
Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.10\))
Subject: Re: [PHP-DEV] bikeshed: Typed Aliases
Date: Tue, 10 Sep 2024 04:00:56 -0400
In-Reply-To: <212fd466-85bc-4447-90b7-8fe5426d1bd1@rwec.co.uk>
Cc: internals@lists.php.net
To: "Rowan Tommins [IMSoP]" <imsop.php@rwec.co.uk>
References: <0fa39535-f22d-4eba-b4df-90abe39e683a@app.fastmail.com>
 <e73be2b0-faa9-42eb-a9f6-8308cf4f8c94@app.fastmail.com>
 <ed3847bf-af2e-4e33-ac09-66e44696fdeb@app.fastmail.com>
 <79e58673-50ec-461e-a998-736b020e4287@app.fastmail.com>
 <a3cd6d90-cfac-40d5-a59a-c9f6d9dbe5f0@app.fastmail.com>
 <928A2984-6035-4DA6-9EA7-12E85237C270@php.net>
 <0d461700-1b6c-44fd-9cda-aa698de49847@app.fastmail.com>
 <667233C2-BC47-4530-8142-D90E6907FE63@daveyshafik.com>
 <D95D21CE-45AB-487A-B59D-40305C0C569D@rwec.co.uk>
 <63d241a8-a34a-498c-a5f9-f34230aa5afa@app.fastmail.com>
 <4C7A7F27-B787-44CA-B664-CEF4B9B412FB@newclarity.net>
 <212fd466-85bc-4447-90b7-8fe5426d1bd1@rwec.co.uk>
X-Mailer: Apple Mail (2.3696.120.41.1.10)
From: mike@newclarity.net (Mike Schinkel)


--Apple-Mail=_4DA80B8B-01DD-4204-BCD4-BDABBD30AC7D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8

> On Sep 9, 2024, at 5:35 PM, Rowan Tommins [IMSoP] =
<imsop.php@rwec.co.uk> wrote:
>=20
> On 09/09/2024 19:41, Mike Schinkel wrote:
>> In Go you cannot add or subtract on a typedef without casting to the=20=

>> underlying type.  I would definitely prefer that to be relaxed, but =
only
>>  if it is relaxed via an explicit opt-in, e.g. something maybe like=20=

>> this:
>>=20
>> typedef UserId: int operations: +, -, *, /;
>> typedef UserName: string operations: .;
> I think this would stray into some of the same complexity as operator =
overloads on objects, in terms of the types and values allowed. For =
instance:
>=20
I tend to agree that allowing operations may be too much for an initial =
scope given that it is unlike anything else in the current language and =
with no other languages offering an equivalent AFAIK.

I would however make the distinction that it is unlike operator =
overloading because the big concern was what constituted an operation =
for any given type could be too subjective.  In your example of `Metres` =
it is pretty obvious, but not at all obvious for a `User`, for example.  =
(BTW, thank you for not calling out my nonsensical example of operations =
on a `UserId`; when I wrote that I clear was not thinking about if they =
were relevant, doh!)

However give the suggestion regarding operations with a typedef, the =
only operations that I suggested would be valid would be the ones =
already defined on the underlying type, (when I mentioned other =
operations I was thinking of methods =E2=80=94 see my the following =
example with round =E2=80=94 not operators so that is not the same as =
operator overload.) For example:

/**
 * Currency is an int so for example in USD 1=20
 * unit of currency not a dollar but a cent.
 */
typedef Currency: int operations: +,-,*,/,round;
function CalcTotal(Currency $subTotal, Currency $shipping, float =
$tax):Currency {
   return round($subTotal*(1+$tax/100),0) + $shipping;
}
> typedef Metres: int;
>=20
> assert( Metres(2) +  Metres(1) =3D=3D=3D Metres(3) ); // most obvious
> assert( Metres(2) + 1 =3D=3D=3D Metres(3) ); // seems pretty clear

Both of those are in line with what I was suggesting.
> $_GET['input'] =3D '1';
> assert( Metres(2) + $_GET['input'] =3D=3D=3D Metres(3) ); // might be =
more controversial
>=20
I would not consider this appropriate as it has two levels of conversion =
and could thus end up with unintended edge cases. To do the above I =
think you would have to either convert or typecast:

assert( Metres(2) + intval($_GET['input']) =3D=3D=3D Metres(3) );=20
assert( Metres(2) + (int)$_GET['input'] =3D=3D=3D Metres(3) );=20
> typedef Feet: int;
> assert( Metres(2) + Feet(1) =3D=3D=3D Metres(3) ); // almost certainly =
a bad idea
>=20
This would be operator overloading where knowledge of the conversion =
between meters and feet would be required, and that is not in any way in =
scope with what I was suggesting. =20

As an aside, I am against userland operator overloading as I have seen =
in other languages that operator overloading gets abused and results in =
code that is a nightmare to maintain. OTOH, I would support operator =
overloading in specific cases, e.g. a `Measurement` class in PHP core =
could allow adding meters to feet, assuming such a proposal were made =
and all other aspects of the RFC were of the nature to be voted in.

To reiterate on typedefs, what I was suggesting was that if an operation =
was explicitly allowed =E2=80=94 e.g. + =E2=80=94 then anything that =
would work with the underlying type =E2=80=94 such as adding an int 1 =
would work without typecasting and yet still result in the typedef type, =
e.g. Meters(2) + 1 results in a value of type Meters. (note that I =
corrected your spelling of 'Meters' here. ;-)=20

But I agree, this is probably a bridge too far for a first RFC for =
typedefs.=20

>> type MyNewType: Foo
>> type MyAlias =3D Foo
> I know this was only an example, but as a general point, I think we =
should avoid concise but cryptic differences like this. PHP is generally =
keyword-heavy, rather than punctuation-heavy, and I think that's a valid =
style which we should keep to.
Here, I also tend to agree WRT PHP.  Was just pointing out for sake of =
laying out other options that were implied not to exist.

-Mike


--Apple-Mail=_4DA80B8B-01DD-4204-BCD4-BDABBD30AC7D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
	charset=utf-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; =
charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; =
-webkit-nbsp-mode: space; line-break: after-white-space;" =
class=3D""><div><blockquote type=3D"cite" class=3D""><div class=3D"">On =
Sep 9, 2024, at 5:35 PM, Rowan Tommins [IMSoP] &lt;<a =
href=3D"mailto:imsop.php@rwec.co.uk" =
class=3D"">imsop.php@rwec.co.uk</a>&gt; wrote:</div><br =
class=3D"Apple-interchange-newline"><div class=3D"">

 =20
    <meta http-equiv=3D"Content-Type" content=3D"text/html; =
charset=3DUTF-8" class=3D"">
 =20
  <div class=3D"">
    <div class=3D"moz-cite-prefix">On 09/09/2024 19:41, Mike Schinkel
      wrote:</div>
    <blockquote type=3D"cite" =
cite=3D"mid:4C7A7F27-B787-44CA-B664-CEF4B9B412FB@newclarity.net" =
class=3D""><pre class=3D"">In Go you cannot add or subtract on a typedef =
without casting to the=20
underlying type.  I would definitely prefer that to be relaxed, but only
 if it is relaxed via an explicit opt-in, e.g. something maybe like=20
this:

typedef UserId: int operations: +, -, *, /;
typedef UserName: string operations: .;</pre></blockquote><p class=3D"">I =
think this would stray into some of the same complexity as
      operator overloads on objects, in terms of the types and values
      allowed. For instance:<br =
class=3D""></p></div></div></blockquote><div>I tend to agree that =
allowing operations may be too much for an initial scope given that it =
is unlike anything else in the current language and with no other =
languages offering an equivalent AFAIK.</div><div><br =
class=3D""></div><div>I would however make the distinction that it is =
unlike operator overloading because the big concern was what constituted =
an operation for any given type could be too subjective. &nbsp;In your =
example of `Metres` it is pretty obvious, but not at all obvious for a =
`User`, for example. &nbsp;(BTW, thank you for not calling out my =
nonsensical example of operations on a `UserId`; when I wrote that I =
clear was not thinking about if they were relevant, doh!)</div><div><br =
class=3D""></div><div>However give the suggestion regarding operations =
with a typedef, the only operations that I suggested would be valid =
would be the ones already defined on the underlying type, (when I =
mentioned other operations I was thinking of methods =E2=80=94 see my =
the following example with round =E2=80=94 not operators so that is not =
the same as operator overload.) For example:</div><div><br =
class=3D""></div><div class=3D""><div class=3D""><font color=3D"#000000" =
class=3D""><span style=3D"caret-color: rgb(0, 0, 0);" class=3D"">/**<br =
class=3D"">&nbsp;* Currency is an int so for example in USD 1&nbsp;<br =
class=3D"">&nbsp;* unit of currency not a dollar but a cent.<br =
class=3D"">&nbsp;*/<br =
class=3D"">typedef&nbsp;Currency:&nbsp;int&nbsp;operations: =
+,-,*,/,round;<br =
class=3D"">function&nbsp;CalcTotal(Currency&nbsp;$subTotal,&nbsp;Currency&=
nbsp;$shipping,&nbsp;float&nbsp;$tax):Currency&nbsp;{<br class=3D"">&nbsp;=
 &nbsp;return&nbsp;round($subTotal*(1+$tax/100),0) +&nbsp;$shipping;<br =
class=3D"">}<br class=3D""></span></font></div></div><blockquote =
type=3D"cite" class=3D""><div class=3D""><div class=3D""><p =
class=3D"">typedef Metres: int;<br class=3D"">
    </p>
    assert( Metres(2) +&nbsp; Metres(1) =3D=3D=3D Metres(3) ); // most =
obvious<br class=3D"">
    assert( Metres(2) + 1 =3D=3D=3D Metres(3) ); // seems pretty =
clear<br class=3D""></div></div></blockquote><div><br =
class=3D""></div>Both of those are in line with what I was =
suggesting.<br class=3D""><blockquote type=3D"cite" class=3D""><div =
class=3D""><div class=3D""><p class=3D"">$_GET['input'] =3D '1';<br =
class=3D"">
      assert( Metres(2) + $_GET['input'] =3D=3D=3D Metres(3) ); // might =
be
      more controversial</p></div></div></blockquote>I would not =
consider this appropriate as it has two levels of conversion and could =
thus end up with unintended edge cases. To do the above I think you =
would have to either convert or typecast:</div><div><br =
class=3D""></div><div>assert( Metres(2) + intval($_GET['input']) =3D=3D=3D=
 Metres(3) );&nbsp;</div><div>assert( Metres(2) + (int)$_GET['input'] =
=3D=3D=3D Metres(3) );&nbsp;</div><div><blockquote type=3D"cite" =
class=3D""><div class=3D""><div class=3D""><p class=3D"">typedef Feet: =
int;<br class=3D"">
      assert( Metres(2) + Feet(1) =3D=3D=3D Metres(3) ); // almost =
certainly a
      bad idea</p></div></div></blockquote>This would be operator =
overloading where knowledge of the conversion between meters and feet =
would be required, and that is not in any way in scope with what I was =
suggesting. &nbsp;</div><div><br class=3D""></div><div>As an aside, I am =
against userland operator overloading as I have seen in other languages =
that operator overloading gets abused and results in code that is a =
nightmare to maintain. OTOH, I would support operator overloading in =
specific cases, e.g. a `Measurement` class in PHP core could allow =
adding meters to feet, assuming such a proposal were made and all other =
aspects of the RFC were of the nature to be voted in.</div><div><br =
class=3D""></div><div>To reiterate on typedefs, what I was suggesting =
was that if an operation was explicitly allowed =E2=80=94 e.g. + =E2=80=94=
 then anything that would work with the underlying type =E2=80=94 such =
as adding an int 1 would work without typecasting and yet still result =
in the typedef type, e.g. Meters(2) + 1 results in a value of type =
Meters. (note that I corrected your spelling of 'Meters' here. =
;-)&nbsp;</div><div><br class=3D""></div><div>But I agree, this is =
probably a bridge too far for a first RFC for =
typedefs.&nbsp;</div><div><br class=3D""><blockquote type=3D"cite" =
class=3D""><div class=3D""><div class=3D""><blockquote type=3D"cite" =
class=3D""><pre class=3D"moz-quote-pre" wrap=3D"">type MyNewType: Foo
type MyAlias =3D Foo</pre>
      </blockquote>
      <p class=3D"">I know this was only an example, but as a general =
point, I think
      we should avoid concise but cryptic differences like this. PHP is
      generally keyword-heavy, rather than punctuation-heavy, and I
      think that's a valid style which we should keep to.<br class=3D"">
    </p></div></div></blockquote>Here, I also tend to agree WRT PHP. =
&nbsp;Was just pointing out for sake of laying out other options that =
were implied not to exist.</div><div><br =
class=3D""></div><div>-Mike</div><br class=3D""></body></html>=

--Apple-Mail=_4DA80B8B-01DD-4204-BCD4-BDABBD30AC7D--