Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125593 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 2B3701A00BD for ; Tue, 17 Sep 2024 17:43:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1726595158; bh=W9bYSOBeYemmCcaqrrmBzN7+9af41iyPrWcFd8VZ5TM=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=btNUNtJwYjkEe9WGanHA1DGJOFzPFqNm6ZZQETjiHJgU6LJjs0dtaaFLwb+rnxhEf iFKA/zcP7iouxpZP9pXPXPXP8GlISW5Uj3a4jhhB4VBVcb2Gm+9I8PeoEhV6iNm57B RpdzErXtYlUZBGXGX2gRHvGZS5Vj0HFrCjpgBcsP/l0B4LWpCLYwshn3B7zdc4cwlE Xh2I/fYVTTiTVdOTl+C+fKDRT9VIGMHANntCqFK86hkoI8fBQeRZEnorBIGh8RzU7H ebWj/BpSbh0Qh9YKYQW6Peo11299YX2jjYeNx5uZQnxXQRoxDf9+7NWg+YpjR5BI1m NWJHD2jGCui/Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2A8E4180068 for ; Tue, 17 Sep 2024 17:45:57 +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.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_PASS,T_KAM_HTML_FONT_INVALID autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 ; Tue, 17 Sep 2024 17:45:56 +0000 (UTC) Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2068bee21d8so59282715ad.2 for ; Tue, 17 Sep 2024 10:43:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1726595031; x=1727199831; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=bk+1/9bvVLTRaIYfygroQZ+4PGPSARtyv1IwUzvVXzw=; b=l7PLKx6H5K6729m4RjmFXW/KAvrcroXMiQEOqY59pO4fPrTzxJ1zidEJ1qZtMsR5rP vXzoykcjQq+ABRn7KYBtpbZGw+TdiByhiVh7NwkD1de6Oq9xmGRfk+nAwRV0qDR0KuMC 1kPfDeceT/0vAQx2smOHd9mABna++QH3RbeYFcWsOw2NtrRuAtxJcuF124dxbGMMbzIL hFhzhwSj66DUPq/C36YrcudoTQgIDYNpbD726WU5XWGfLiGQAhwY/yhDwLxqGUcP6FZL z/hoDDsxXgnZYCwQvhwkkp8ATJSxRDg6dqyjsm6F9tqWAfq4PGQ8837bEK5llidlzjFm QadQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726595031; x=1727199831; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=bk+1/9bvVLTRaIYfygroQZ+4PGPSARtyv1IwUzvVXzw=; b=Q9WDWl3X/912z8ZzI12570Cw64cojj9Mc16uYClMZgfxlDNHX/T7OhhcU9dHZvbC4U 6WnslV9uY5XBhxIJJ5LaoxuQi8FhRCKPpfICI4x3lMy5gYzGvoLviRlhgZH60xEqF6Iq E3SxwbjZz0iG45ipzNFUhbdfPgL2o0mQ0i7DPutSm9Mf3R1iKaXtQk8ufIglFDXCHyHd lB1D+t4RCtSI6o3taituoi2cNKGBAjjoxffqlxPVOGO0Q2pi8TsKazYbLHDWsapY7GjA fkkVDXz0jq/2/yzRrMQlCxA58knEIAEeImJRz4hLO6/QiuuT07gmK3jyD777MFkU3n4w bcLA== X-Gm-Message-State: AOJu0YxHDIRmTG9EYeitunoh85+/TGorKLEri1LBSwjtTNetx/YFIo61 Aopg8OPiRGb5RcOlgGvFfKZEuKqQgNJvjHmMj2ex06vwKYv7v2jxK4Vxc0y1D/3D89V4IMGLy82 PWggg/MTb00jsqV9S0wTwFt2prMWHUw== X-Google-Smtp-Source: AGHT+IGbD3UM0OIAbWUDrlmASGQJnkcqcvCiM9es1YF6wj/8fg4h/Y2rEUeDhH3eX/pw3EjfX7Cv0QKxkOlVinO6eqo= X-Received: by 2002:a17:903:110e:b0:207:1722:37d4 with SMTP id d9443c01a7336-2076e3a2307mr265834465ad.33.1726595030469; Tue, 17 Sep 2024 10:43:50 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Tue, 17 Sep 2024 10:43:39 -0700 Message-ID: Subject: Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again) To: Lynn Cc: PHP internals Content-Type: multipart/alternative; boundary="0000000000007656c30622543b44" From: jordan.ledoux@gmail.com (Jordan LeDoux) --0000000000007656c30622543b44 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, Sep 17, 2024 at 2:56=E2=80=AFAM Lynn wrote: > > > On Sat, Sep 14, 2024 at 11:51=E2=80=AFPM Jordan LeDoux > wrote: > >> Hello internals, >> >> This discussion will use my previous RFC as the starting point for >> conversation: https://wiki.php.net/rfc/user_defined_operator_overloads >> >> There has been discussion on list recently about revisiting the topic of >> operator overloads after the previous effort which I proposed was declin= ed. >> There are a variety of reasons, I think, this is being discussed, both o= n >> list and off list. >> >> 1. As time has gone on, more people have come forward with use cases. >> Often they are use cases that have been mentioned before, but it has bec= ome >> more clear that these use cases are more common than was suggested >> previously. >> >> 2. Several voters, contributors, and participants have had more time >> (years now) to investigate and research some of the related issues, whic= h >> naturally leads to changes in opinion or perspective. >> >> 3. PHP has considered and been receptive toward several RFCs since my >> original proposal which update the style of PHP in ways which are congru= ent >> with the KIND of language that has operator overloads. >> >> I mentioned recently that I would not participate in another operator >> overload RFC unless I felt that the views of internals had become more >> receptive to the topic, and after some discussion with several people >> off-list, I feel that it is at least worth discussing for the next versi= on. >> >> Operator overloads has come up as a missing feature in several >> discussions on list since the previous proposal was declined. This inclu= des: >> >> [RFC] [Discussion] Support object type in BCMath [1] >> >> Native decimal scalar support and object types in BcMath [2] >> >> Custom object equality [3] >> >> pipes, scalar objects and on? [4] >> >> [RFC][Discussion] Object can be declared falsifiable [5] >> >> The request to support comparison operators (>, >=3D, =3D=3D, !=3D, <=3D= , <, <=3D>) >> has come up more frequently, but particularly in discussion around linea= r >> algebra, arbitrary precision mathematics, and dimensional numbers (such = as >> currency or time), the rest of the operators have also come up. >> >> Typically, these use cases are themselves very niche, but the >> capabilities operator overloads enable would be much more widely used. F= rom >> discussion on list, it seems likely that very few libraries would need t= o >> implement operator overloads, but the libraries that do would be well us= ed >> and thus MANY devs would be consumers of operator overloads. >> >> I want to discuss what changes to the previous proposal people would be >> seeking, and why. The most contentious design choice of the previous >> proposal was undoubtedly the `operator` keyword and the decision to make >> operator overload implementations distinct from normal magic methods. Fo= r >> some of the voters who voted yes on the previous RFC, this was a "killer >> feature" of the proposal, while for some of the voters who voted no it w= as >> the primary reason they were against the feature. >> >> There are also several technical and tangentially related items that are >> being worked on that would be necessary for operator overloads (and were >> originally included in my implementation of the previous RFC). This >> includes: >> >> 1. Adding a new opcode for LARGER and LARGER_OR_EQUAL so that operand >> position can be preserved during ALL comparisons. >> >> 2. Updating ZEND_UNCOMPARABLE such that it has a value other than -1, 0, >> or 1 which are typically reserved during an ordering comparison. >> >> 3. Allowing values to be equatable without also being orderable (such as >> with matrices, or complex numbers). >> >> These changes could and should be provided independent of operator >> overloads. Gina has been working on a separate RFC which would cover all >> three of these issues. You can view the work-in-progress on that RFC her= e: >> https://github.com/Girgias/php-rfcs/blob/master/comparison-equality-sema= ntics.md >> >> I hope to start off this discussion productively and work towards >> improving the previous proposal into something that voters are willing t= o >> pass. To do that, I think these are the things that need to be discussed= in >> this thread: >> >> 1. Should the next version of this RFC use the `operator` keyword, or >> should that approach be abandoned for something more familiar? Why do yo= u >> feel that way? >> >> 2. Should the capability to overload comparison operators be provided in >> the same RFC, or would it be better to separate that into its own RFC? W= hy >> do you feel that way? >> >> 3. Do you feel there were any glaring design weaknesses in the previous >> RFC that should be addressed before it is re-proposed? >> >> 4. Do you feel that there is ANY design, version, or implementation of >> operator overloads possible that you would support and be in favor of, >> regardless of whether it matches the approach taken previously? If so, c= an >> you describe any of the core ideas you feel are most important? >> >> Jordan >> >> External Links: >> >> [1]: https://externals.io/message/122735 >> >> [2]: https://externals.io/message/122994 >> >> [3]: https://externals.io/message/121387 >> >> [4]: https://externals.io/message/120822 >> >> [5]: https://externals.io/message/118971 >> >> > I'm not experienced with other languages and overloading, so consider thi= s > reply as me not knowing enough about the subject. Rowan asked an > interesting question: "Are we over-riding *operators* or *operations*?" > which made me think about behaviors as a 3rd alternative. Instead of > individual operator overloading, could classes define how they would act = as > certain primitives or types that have overloading under the hood? We have > `Stringable` with `__toString`, which might not be the best example but > does point in a similar direction. I don't know if this is a direction > worth exploring but wanted to at least bring it up. > > ```php > interface IntBehavior { > public function asInt(): int; > } > > class PositiveInt implements IntBehavior { > public readonly int $value; > public function __construct(int $value) { > $this->value =3D max(0, $value); > } > public function asInt(): int { > return $this->value; > } > } > > var_dump(10 + new PositiveInt(5)); // 15 > var_dump(new PositiveInt(10) + 15); // 25 > var_dump(new PositiveInt(100) + new PositiveInt(100)); // 200 > > // leaves it to the developer to do: > $number =3D new PositiveInt(new PositiveInt(10) + 5); > ``` > > I actually did explore something like this during my initial design phases before ever bringing it up on list the first time. I decided that it was certainly useful, and perhaps even something I would also want, but did not solve the problem I was trying to solve. The problem I was trying to solve involved lots of things that cannot be represented well by primitive types (which is presumably why they are classes in the first place). Things like Complex Numbers, Matrices, or Money. Money can be converted to a float of course (or an int depending on implementation), but Money does not want to be added with something like request count, which might also be an int. Or if it does, it probably wants to know exactly what the context is. There are lots of these kinds of value classes that might be representable with scalars, but would lose a lot of their context and safety if that is done. On the other hand, Money would probably not want to be multiplied with other Money values. What would Money squared mean exactly? Things like this are very difficult to control for if all you provide is a way to control casting to scaar types. Jordan --0000000000007656c30622543b44 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


=
On Tue, Sep 17, 2024 at 2:56=E2=80=AF= AM Lynn <kjarli@gmail.com> wr= ote:


On Sat, Sep 14, 2024 at 11:51=E2=80=AFPM Jordan = LeDoux <jor= dan.ledoux@gmail.com> wrote:

Hello internals,


This= discussion will use my previous RFC as the starting point for conversation= : https= ://wiki.php.net/rfc/user_defined_operator_overloads


Ther= e has been discussion on list recently about revisiting the topic of operat= or overloads after the previous effort which I proposed was declined. There= are a variety of reasons, I think, this is being discussed, both on list a= nd off list.


1. As time has gone on, more people have come f= orward with use cases. Often they are use cases that have been mentioned be= fore, but it has become more clear that these use cases are more common tha= n was suggested previously.

2. Several voters, contributors, and= participants have had more time (years now) to investigate and research so= me of the related issues, which naturally leads to changes in opinion or pe= rspective.

3. PHP has considered and been receptive toward sever= al RFCs since my original proposal which update the style of PHP in ways wh= ich are congruent with the KIND of language that has operator overloads.


I mentioned recently that I would not participate in another o= perator overload RFC unless I felt that the views of internals had become m= ore receptive to the topic, and after some discussion with several people o= ff-list, I feel that it is at least worth discussing for the next version.<= /span>


Operator overloads has come up as a missing feature in sever= al discussions on list since the previous proposal was declined. This inclu= des:


[RFC] [Discussion] Support object type in BCMath [1]

Native decimal scalar support and object types in BcMath [2]

Custom object equality [3]

pipes, scalar objects and on? [= 4]

[RFC][Discussion] Object can be declared falsifiable [5]


The request to support comparison operators (>, >=3D, =3D= =3D, !=3D, <=3D, <, <=3D>) has come up more frequently, but par= ticularly in discussion around linear algebra, arbitrary precision mathemat= ics, and dimensional numbers (such as currency or time), the rest of the op= erators have also come up.


Typically, these use cases are th= emselves very niche, but the capabilities operator overloads enable would b= e much more widely used. From discussion on list, it seems likely that very= few libraries would need to implement operator overloads, but the librarie= s that do would be well used and thus MANY devs would be consumers of opera= tor overloads.


I want to discuss what changes to the previou= s proposal people would be seeking, and why. The most contentious design ch= oice of the previous proposal was undoubtedly the `operator` keyword and th= e decision to make operator overload implementations distinct from normal m= agic methods. For some of the voters who voted yes on the previous RFC, thi= s was a "killer feature" of the proposal, while for some of the v= oters who voted no it was the primary reason they were against the feature.=


There are also several technical and tangentially related i= tems that are being worked on that would be necessary for operator overload= s (and were originally included in my implementation of the previous RFC). = This includes:


1. Adding a new opcode for LARGER and LARGER_= OR_EQUAL so that operand position can be preserved during ALL comparisons.<= /span>

2. Updating ZEND_UNCOMPARABLE such that it has a value other tha= n -1, 0, or 1 which are typically reserved during an ordering comparison.

3. Allowing values to be equatable without also being orderable (= such as with matrices, or complex numbers).


These changes co= uld and should be provided independent of operator overloads. Gina has been= working on a separate RFC which would cover all three of these issues. You= can view the work-in-progress on that RFC here: https://github.com/Girgias/php-rfcs/blob/master/comparison-equa= lity-semantics.md


I hope to start off this discussion pr= oductively and work towards improving the previous proposal into something = that voters are willing to pass. To do that, I think these are the things t= hat need to be discussed in this thread:


1. Should= the next version of this RFC use the `operator` keyword, or should that ap= proach be abandoned for something more familiar? Why do you feel that way?<= /span>

2. Should the capability to overload comparison operat= ors be provided in the same RFC, or would it be better to separate that int= o its own RFC? Why do you feel that way?

3. Do you fee= l there were any glaring design weaknesses in the previous RFC that should = be addressed before it is re-proposed?

4. Do you feel = that there is ANY design, version, or implementation of operator overloads = possible that you would support and be in favor of, regardless of whether i= t matches the approach taken previously? If so, can you describe any of the= core ideas you feel are most important?


Jordan

External Links:

[1]: https://externals.io/message/122735

[2]: https://externals.io/message/122994

[3]: https://externals.io/messa= ge/121387

[4]: https://externals.io/message/120822

[5]= : https:/= /externals.io/message/118971



=
I'm not experienced with other languages and overloading, so= consider this reply as me not knowing enough about the subject. Rowan aske= d an interesting question: "Are we over-riding *operators* or *operati= ons*?" which made me think about behaviors as a 3rd alternative. Inste= ad of individual operator overloading, could classes define how they would = act as certain primitives or types that have overloading under the hood? We= have `Stringable` with `__toString`, which might not be the best example b= ut does point in a similar direction. I don't know if this is a directi= on worth exploring but wanted to at least bring it up.

=
```php
interface IntBehavior {
=C2=A0 =C2=A0 publi= c function asInt(): int;
}

class Positiv= eInt implements IntBehavior {
=C2=A0 =C2=A0 public readonly int $= value;
=C2=A0 =C2=A0 public function __construct(int $value) = {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $this->value =3D max(0, $value);=
=C2=A0 =C2=A0 }
=C2=A0 =C2=A0 public function asInt():= int {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return $this->value;
<= div>=C2=A0 =C2=A0 }
}

var_dump(10=C2=A0+= new PositiveInt(5)); // 15
var_dump(new PositiveInt(10)=C2=A0+ 15); /= / 25
var_dump(new PositiveInt(100)=C2=A0+ new PositiveInt(100)); // 200<= /div>

// lea= ves it to the developer to do:
$number =3D = new PositiveInt(new PositiveInt(10)=C2=A0+ 5);
```

<= br>
I actually did explore something like this during my initial = design phases before ever bringing it up on list the first time. I decided = that it was certainly useful, and perhaps even something I would also want,= but did not solve the problem I was trying to solve.=C2=A0

<= /div>
The problem I was trying to solve involved lots of things that ca= nnot be represented well by primitive types (which is presumably why they a= re classes in the first place). Things like Complex Numbers, Matrices, or M= oney. Money can be converted to a float of course (or an int depending on i= mplementation), but Money does not want to be added with something like req= uest count, which might also be an int. Or if it does, it probably wants to= know exactly what the context is. There are lots of these kinds of value c= lasses that might be representable with scalars, but would lose a lot of th= eir context and safety if that is done.

On the oth= er hand, Money would probably not want to be multiplied with other Money va= lues. What would Money squared mean exactly? Things like this are very diff= icult to control for if all you provide is a way to control casting to scaa= r types.

Jordan
--0000000000007656c30622543b44--