Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:124041
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 84F5E1A009C
	for <internals@lists.php.net>; Sat, 29 Jun 2024 15:21:43 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
	t=1719674582; bh=KfArFvCSr/igDj40pCIIY/bMgWjrbpsy5yPjq+yvpoI=;
	h=In-Reply-To:References:Date:From:To:Cc:Subject:From;
	b=d0nctLXEAJ7xDXMd5WaAviCbnHK4BotuZJAY7sKY7j/avwpYnYRdgBURgctkBvyhk
	 hM98mBJbtnWdcssP0vmkM/gGmOtia4kilsJT8stkBV7p48TTso5nQpGiPkLPymfnJy
	 5WvWpq5bf/G5HleFnhrji6jzASDzLR4kmKiV0FKVVuWWfHVpw2MD2NKjEIVhf4iNJx
	 sxbh7Nev6E9o3a/JgcJE2zokdO+fqpCCQ8PLpSblVaHCeEaqxkIi7dZk5E8B266bhR
	 oEmBMpwvehlQKo9/3WPCJMqAgtayFeUQkpA2vbuKHD57y3vZpVfWqADvEr/jitNA0L
	 VBj/87gHRhf5w==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id E30BC1813EA
	for <internals@lists.php.net>; Sat, 29 Jun 2024 15:22:58 +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,SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE
	autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: Error (Cannot connect to unix socket
	'/var/run/clamav/clamd.ctl': connect: Connection refused)
X-Envelope-From: <rob@bottled.codes>
Received: from fout6-smtp.messagingengine.com (fout6-smtp.messagingengine.com [103.168.172.149])
	(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>; Sat, 29 Jun 2024 15:22:56 +0000 (UTC)
Received: from compute1.internal (compute1.nyi.internal [10.202.2.41])
	by mailfout.nyi.internal (Postfix) with ESMTP id BAF6B13801A1;
	Sat, 29 Jun 2024 11:21:36 -0400 (EDT)
Received: from imap49 ([10.202.2.99])
  by compute1.internal (MEProxy); Sat, 29 Jun 2024 11:21:36 -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=fm3; t=1719674496; x=
	1719760896; bh=KfArFvCSr/igDj40pCIIY/bMgWjrbpsy5yPjq+yvpoI=; b=P
	AJQq2cA65b+SxZlxtlaOZ2bxS/CIc6orUiXEtSZzEH/5YE7fZFDp/KN3jOuXRvEl
	RaCdrb7oRmMavvPXKr2RFfCaZ3ycGTRJ7q7YE02IpNBbAdA1JInE37hPxO/Drd4c
	9xGlJKb6zSzIJBtcz+pWFGnFZnpuGXiG3N2HUUxLJWMJ38iRSCichuztMjDVU0jJ
	FYGCcdfBLAzuax5QlgmSgy/D1qjF9Ot4S1a2N96Ec/KymgHF8LenF4DliHFPFgTL
	9cLiz+dSUWcyd1bIJie2QmF04R7KUHkqtIkbWCRe95nlQ9GI/Pm7u4xZfjo4P0YI
	tXo0bPaxpDF+yd9IvAuCA==
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-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=
	fm2; t=1719674496; x=1719760896; bh=KfArFvCSr/igDj40pCIIY/bMgWjr
	bpsy5yPjq+yvpoI=; b=uP4aRSU6uNVbPK7+4hh/FCpyL1j1D5bS9EmBdDA1m3ec
	sJ6+IkEbshgprewUlfD9QoQ0vMLO0+6s9gpydrYld2OtQSU+35SbBZsg3mvT3fLw
	Np6NrvsVO7AVIEtp76HQKD7WYzWUAE0DoWpYkwGoeeHzdZ7nMRJ8XnoHxXewi53c
	WmfWupMffaRizzS9fUFl9Fp8N4X2tgRT2khlQ9D4xcJVthHTs/x5J77vB95Yqf2q
	mGXXs4NZ+YZLBtlYO9pZ+QUxNUprToTxD0aAsJzCzmEBn/Vz6+Sfx3jGx8ERMLa4
	H9SnySAdv3s2+rhsuqTswwRnu1NjwE/yMcHOe6h5Lw==
X-ME-Sender: <xms:gCaAZnCn_P4MF4oUsRUFI6ELBYFkB1rWz_X-K37Hhv067c6cIsfBGg>
    <xme:gCaAZtgGOFO9DMDqHdNVVfdxXvX6wQcROjGyxgfr5MeDtzYbIlFC0Hv3VqU9x_w6N
    sFhMXceLvYevTWkJ_k>
X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrtdelgdekkecutefuodetggdotefrodftvf
    curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu
    uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc
    fjughrpefofgggkfgjfhffhffvvefutgesrgdtreerreerjeenucfhrhhomhepfdftohgs
    ucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurdgtohguvghsqeenucggtffrrg
    htthgvrhhnpedvheekteelveetfeevgeekgfffvdeuhfelveehvdetiefggedtfeejheet
    gffhueenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe
    hrohgssegsohhtthhlvggurdgtohguvghs
X-ME-Proxy: <xmx:gCaAZilSgVufSOqhALN_KZh-QqQr8m0qlGF_Qefo3RgPPgrhvw_x_g>
    <xmx:gCaAZpw9kLZZ9XzQrWiOlAh2Aedb8HL8qJpGwtHBaZ7PTetK4StLsA>
    <xmx:gCaAZsQn2KJwx-qCWEVIYfxeXDCqdHgXb1PMP50QHNsLruVWDR5d7g>
    <xmx:gCaAZsaiWat8t4LPixOSfGzRhVz-VG_3LyaNqDaRQZM1Ey6gYo358w>
    <xmx:gCaAZnfprnY9fb-pHN5Lwlrz0txSBFd02iF0M5HcPXxJI5XhRbNtONz6>
Feedback-ID: ifab94697:Fastmail
Received: by mailuser.nyi.internal (Postfix, from userid 501)
	id 7182515A0092; Sat, 29 Jun 2024 11:21:36 -0400 (EDT)
X-Mailer: MessagingEngine.com Webmail Interface
User-Agent: Cyrus-JMAP/3.11.0-alpha0-538-g1508afaa2-fm-20240616.001-g1508afaa
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
MIME-Version: 1.0
Message-ID: <535cbdef-a6a1-4ca6-9cc6-0839bb2e833b@app.fastmail.com>
In-Reply-To: <DD3C5488-4C11-4393-A45D-60F8C49B4DA0@sakiot.com>
References: <90ab0ec1-33ad-4342-ad4b-6448ee89bfa7@app.fastmail.com>
 <DD3C5488-4C11-4393-A45D-60F8C49B4DA0@sakiot.com>
Date: Sat, 29 Jun 2024 17:21:16 +0200
To: "Saki Takamachi" <saki@sakiot.com>
Cc: "Jordan LeDoux" <jordan.ledoux@gmail.com>, internals@lists.php.net
Subject: Re: [PHP-DEV] [RFC] Operator Overrides -- Lite Edition
Content-Type: multipart/alternative;
 boundary=284552c1df484ef38e73143ee302239d
From: rob@bottled.codes ("Rob Landers")

--284552c1df484ef38e73143ee302239d
Content-Type: text/plain;charset=utf-8
Content-Transfer-Encoding: quoted-printable

On Sat, Jun 29, 2024, at 16:19, Saki Takamachi wrote:
> Hi,
>=20
> >> Here are my thoughts on your code.
> >>=20
> >> In theory, inheriting from this "improved GMP class" would allow ov=
erloading of computational operators.
> >>=20
> >> In effect, this acts like a "calcable interface", with the construc=
tor passing in meaningless values to the parent constructor and the add =
method allowing the user to freely modify the return value.
> >>=20
> >> This means that virtually any userland class can use the operator o=
verloading feature via a "hack".
> >=20
> > That is a very valid point, and I feel like it is something I defini=
tely would have thought about since I love abusing features to do things=
 they shouldn't. My hope was that by removing the ability to directly co=
mpare, it would reduce the usefulness of "hacking it" into generic overl=
oading since you have to return a GMP instance ... but then, I guess, th=
at GMP instance technically doesn't have to represent a number (though t=
he rest of the engine will very much treat it as a number).
> >=20
> > I will think on this some more...
> >=20
> > For example, while eating lunch, I was considering whether this even=
 needs to have anything to do with the GMP instance. I was only focusing=
 on the GMP class because right now, it is non-final. Then I started thi=
nking about Jordan's original proposal and how it could be simplified ..=
. there's certainly things to think about.
> >=20
> >> This approach is completely wrong.
> >=20
> > Ouch, I would hope it would have something useful to it. :)
> >=20
> >>=20
> >> Rather than proposing this as is, it would be more constructive to =
propose support for operator overloading.
> >=20
> > That's been tried before, and this was an attempt at the far other e=
xtreme, "barely operator overloading". So, there is surely something in =
the middle. Hopefully.
> >=20
> > =E2=80=94 Rob
>=20
> I would like to state my opinion on this matter, making it clear that =
I am of the opinion that "GMP class should be final."

Yes, the more I consider it, the name of the base class will probably ch=
ange, though GMP is a good candidate as a base class for "overridable nu=
mbers" for multiple reasons:
 1. near infinite numeric resolution
 2. arbitrarily big numbers (At least I've used it to perform operations=
 on 256bit+ numbers)
 3. pretty fast
This gives a lot of power to whatever number is stored there and isn't l=
imited to float or integer.

Secondly, numbers are pretty much the only thing you can't override in P=
HP. There's ArrayAccess if you want custom array-like things and there i=
s Stringable if you want to control how your object is concatenated. The=
re's no way to say "this number is a duration and you multiplying durati=
on times how many cows you have is probably nonsensical." while also sti=
ll allowing you to cast to an int/float if you want to do it anyway. Sur=
e, you can write out $num->times($otherNum), but that isn't scannable or=
 idiomatic to numbers, in general. What you (or at least I) want to do i=
s write $num * $otherNum, especially because working out the order of op=
erations is easy.

Before we switched to GMP on a project, working out $num->mul($other->mi=
nus($v->pow(2)))) was really hard to follow. With GMP it turned into $nu=
m * ($other - ($v ** 2)). Where it got really hard were things like $num=
 * $other - $v * 3. Looking at this, you already know the order of opera=
tions, you know that $num * other, then $v * 3 comes first. When writing=
 it out, you have to specifically state the order of operations: $num->m=
ul($other)->sub($v->mul(3))).

It's really easy to mess that up.

>=20
> First of all, to meet the requirements that are the basis of this disc=
ussion, it is not actually necessary to expose the calculation logic; it=
 is enough to simply specify the class of result.
>=20
> A practical approach to get around this issue is to tell php what clas=
s the result should be.
>=20
> For example, could prepare a method like `resultClass(string $num1Clas=
s, string $num2Class, string $calcType): string|false`, and return the c=
lass name of the result based on the class names of the two objects to b=
e calculated and the calculation type, such as addition or subtraction.
>=20
> PHP calls this method as a "hook" when it finishes a calculation and r=
eturns the result to determine the class of the return value.
>=20
> But I don't like this because it's a "hacky" way of doing things with =
zend. Also, I am concerned about the cost of doing this for every calcul=
ation.
>=20
> The reason I'm putting together what I consider to be a bad method is =
because it's possible that you or someone else will take my idea, add a =
twist that I haven't thought of, and come up with a way to make it all w=
ork.

Interesting.

>=20
> Regards,
>=20
> Saki
>=20

=E2=80=94 Rob
--284552c1df484ef38e73143ee302239d
Content-Type: text/html;charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html><html><head><title></title><style type=3D"text/css">p.Mso=
Normal,p.MsoNoSpacing{margin:0}
p.MsoNormal,p.MsoNoSpacing{margin:0}</style></head><body><div>On Sat, Ju=
n 29, 2024, at 16:19, Saki Takamachi wrote:<br></div><blockquote type=3D=
"cite" id=3D"qt" style=3D""><div>Hi,<br></div><div><br></div><div>&gt;&g=
t; Here are my thoughts on your code.<br></div><div>&gt;&gt;&nbsp;<br></=
div><div>&gt;&gt; In theory, inheriting from this "improved GMP class" w=
ould allow overloading of computational operators.<br></div><div>&gt;&gt=
;&nbsp;<br></div><div>&gt;&gt; In effect, this acts like a "calcable int=
erface", with the constructor passing in meaningless values to the paren=
t constructor and the add method allowing the user to freely modify the =
return value.<br></div><div>&gt;&gt;&nbsp;<br></div><div>&gt;&gt; This m=
eans that virtually any userland class can use the operator overloading =
feature via a "hack".<br></div><div>&gt;&nbsp;<br></div><div>&gt; That i=
s a very valid point, and I feel like it is something I definitely would=
 have thought about since I love abusing features to do things they shou=
ldn't. My hope was that by removing the ability to directly compare, it =
would reduce the usefulness of "hacking it" into generic overloading sin=
ce you have to return a GMP instance ... but then, I guess, that GMP ins=
tance technically doesn't have to represent a number (though the rest of=
 the engine will very much treat it as a number).<br></div><div>&gt;&nbs=
p;<br></div><div>&gt; I will think on this some more...<br></div><div>&g=
t;&nbsp;<br></div><div>&gt; For example, while eating lunch, I was consi=
dering whether this even needs to have anything to do with the GMP insta=
nce. I was only focusing on the GMP class because right now, it is non-f=
inal. Then I started thinking about Jordan's original proposal and how i=
t could be simplified ... there's certainly things to think about.<br></=
div><div>&gt;&nbsp;<br></div><div>&gt;&gt; This approach is completely w=
rong.<br></div><div>&gt;&nbsp;<br></div><div>&gt; Ouch, I would hope it =
would have something useful to it. :)<br></div><div>&gt;&nbsp;<br></div>=
<div>&gt;&gt;&nbsp;<br></div><div>&gt;&gt; Rather than proposing this as=
 is, it would be more constructive to propose support for operator overl=
oading.<br></div><div>&gt;&nbsp;<br></div><div>&gt; That's been tried be=
fore, and this was an attempt at the far other extreme, "barely operator=
 overloading". So, there is surely something in the middle. Hopefully.<b=
r></div><div>&gt;&nbsp;<br></div><div>&gt; =E2=80=94 Rob<br></div><div><=
br></div><div>I would like to state my opinion on this matter, making it=
 clear that I am of the opinion that "GMP class should be final."<br></d=
iv></blockquote><div><br></div><div>Yes, the more I consider it, the nam=
e of the base class will probably change, though GMP is a good candidate=
 as a base class for "overridable numbers" for multiple reasons:<br></di=
v><ol><li>near infinite numeric resolution<br></li><li>arbitrarily big n=
umbers (At least I've used it to perform operations on 256bit+ numbers)<=
br></li><li>pretty fast<br></li></ol><div>This gives a lot of power to w=
hatever number is stored there and isn't limited to float or integer.<br=
></div><div><br></div><div>Secondly, numbers are pretty much the only th=
ing you can't override in PHP. There's ArrayAccess if you want custom ar=
ray-like things and there is Stringable if you want to control how your =
object is concatenated. There's no way to say "this number is a duration=
 and you multiplying duration times how many cows you have is probably n=
onsensical." while also still allowing you to cast to an int/float if yo=
u want to do it anyway. Sure, you can write out $num-&gt;times($otherNum=
), but that isn't scannable or idiomatic to numbers, in general. What yo=
u (or at least I) want to do is write $num * $otherNum, especially becau=
se working out the order of operations is easy.<br></div><div><br></div>=
<div>Before we switched to GMP on a project, working out $num-&gt;mul($o=
ther-&gt;minus($v-&gt;pow(2)))) was really hard to follow. With GMP it t=
urned into $num * ($other - ($v ** 2)). Where it got really hard were th=
ings like $num * $other - $v * 3. Looking at this, you already know the =
order of operations, you know that $num * other, then $v * 3 comes first=
. When writing it out, you have to specifically state the order of opera=
tions: $num-&gt;mul($other)-&gt;sub($v-&gt;mul(3))).<br></div><div><br><=
/div><div>It's really easy to mess that up.</div><div><br></div><blockqu=
ote type=3D"cite" id=3D"qt" style=3D""><div><br></div><div>First of all,=
 to meet the requirements that are the basis of this discussion, it is n=
ot actually necessary to expose the calculation logic; it is enough to s=
imply specify the class of result.<br></div><div><br></div><div>A practi=
cal approach to get around this issue is to tell php what class the resu=
lt should be.<br></div><div><br></div><div>For example, could prepare a =
method like `resultClass(string $num1Class, string $num2Class, string $c=
alcType): string|false`, and return the class name of the result based o=
n the class names of the two objects to be calculated and the calculatio=
n type, such as addition or subtraction.<br></div><div><br></div><div>PH=
P calls this method as a "hook" when it finishes a calculation and retur=
ns the result to determine the class of the return value.<br></div><div>=
<br></div><div>But I don't like this because it's a "hacky" way of doing=
 things with zend. Also, I am concerned about the cost of doing this for=
 every calculation.<br></div><div><br></div><div>The reason I'm putting =
together what I consider to be a bad method is because it's possible tha=
t you or someone else will take my idea, add a twist that I haven't thou=
ght of, and come up with a way to make it all work.<br></div></blockquot=
e><div><br></div><div>Interesting.</div><div><br></div><blockquote type=3D=
"cite" id=3D"qt" style=3D""><div><br></div><div>Regards,<br></div><div><=
br></div><div>Saki<br></div><div><br></div></blockquote><div><br></div><=
div id=3D"sig121229152">=E2=80=94 Rob<br></div></body></html>
--284552c1df484ef38e73143ee302239d--