> On Sep 14, 2024, at 5:48 PM, Jordan LeDoux <jordan.led...@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
> 
> There has been discussion on list recently about revisiting the topic of 
> operator 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 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 become 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, which 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 congruent 
> 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 version.
> 
> Operator overloads has come up as a missing feature in several discussions on 
> list since the previous proposal was declined. This includes:
> 
> [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 (>, >=, ==, !=, <=, <, <=>) has 
> come up more frequently, but particularly in discussion around linear 
> 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. From discussion on 
> list, it seems likely that very few libraries would need to implement 
> operator overloads, but the libraries that do would be well used 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. For 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 was 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 here: 
> https://github.com/Girgias/php-rfcs/blob/master/comparison-equality-semantics.md
> 
> I hope to start off this discussion productively and work towards improving 
> the previous proposal into something that voters are willing to pass. To do 
> that, I think these are the things that need to be discussed in this thread:

Anyone who just happened to see my prior messages on the topic know that I have 
strongly advocated against operator overloads.

Rather than repeat my full arguments on the list, I will instead summarize by 
linking to three (3) of the comments from Jordan's Reddit poll, two of them 
mine.  If you *only* read one of them, read the *last* one:

- https://www.reddit.com/r/PHP/comments/rv11fc/comment/hr2ujix/ 
<https://www.reddit.com/r/PHP/comments/rv11fc/comment/hr2ujix/>
- https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnha4gq/ 
<https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnha4gq/>
- https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnhcbqr/ 
<https://www.reddit.com/r/PHP/comments/rv11fc/comment/lnhcbqr/>

Basically my concerns are that operator overloading has benefits for a subset 
of developers that are certainly in the minority — developers using PHP for 
math, scientific and similar fields — and yet it would place a burden on 
everyone. That is why I have been against it.

HOWEVER, today I identified an approach that would allow me support operator 
overloading and that is to reduce the scope in which the use of operator 
overloads are valid. 

But let me answer the questions before I elaborate.

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

I have no strong opinion on using `operator`, pro or con

OTOH I would prefer that operators are spelled out vs. just the sigil, e.g. 
`add` and `minus` vs. `+` and `-`. They would be easier and quicker for 
refactoring IDEs to find them with fewer false positives, especially in text  
vs code, and they would be easier to "see" when scanning source code.  

That said, this is not a hill I want to die on so I am just registering my 
opinion and then will move on.

> 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? Why do you 
> feel that way?

I have no strong opinion on this.

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

Yes, the fact that there were no constraints of the nature I propose below.

> 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, can 
> you describe any of the core ideas you feel are most important?

Yes, if constraints of the nature I propose below are adopted.

The biggest problem I have with operator overloads is that — once added — all 
code could potentially be "infected" with operator overloads. However, if the 
developer *using* an operator overload could instead opt-in to using them, in 
context, then I would flip my opinion and I would begin to support them.  

What might opt-in look like?  I propose two (2) mechanisms of which each would 
be useful for different use-cases. As such I do not see these two as competing 
but instead would expect adding both to be preferable:

1. Add a pair of sigils to enclose any expression that would need to support 
userland operator overloading. This would allow a developer to isolate just the 
expression that needs to use operator overloading. I propose {[...]} for this, 
but feel free to bikeshed sigils. Using an example from the RFC, here is what 
code might look like:

$cnum1 = new ComplexNumber(1, 2);
$cnum2 = new ComplexNumber(3, 4);
$cnum3 = {[ $cnum1 * $cnum2 ]};               // Uses operator operloading 
sigils
echo $cnum3->realPart.' + '.$cnum3->imaginaryPart.'i';

2. For when using `{[...]}` would be annoying because it would be needed in so 
many places, PHP could also add support for an attribute. e.g. 
`#[OperatorOverloads(Userland:true)]`. This attribute would apply to functions, 
methods, classes, enums, (other?) and indicates that operator overloads can be 
present anywhere in the body of the decorated structure. I included 
`Userland:true` as an indicator to a reader that this only applies to userland 
operator overloads and that built-in ones like in GMP and anywhere else would 
not need to be opted into, but that parameter could of course be dropped if 
others feel it is not needed. Again, feel free to bikeshed attribute name 
and/or parameters.

#[OperatorOverloads(Userland:true)]
function SprintProductOfTwoComplex(ComplexNumber $cnum1, ComplexNumber 
$cnum2)string {
  $cnum3 = $cnum1 * $cnum2;
  return sprintf("%d + %di", $cnum3->realPart, $cnum3->imaginaryPart);
}

If this approach were included in the RFC then it would also ensure there is no 
possibility of BC breakage. BC breakage which would certainly be an edge case 
but I can envision it would be possible,e specially where newer instances 
incorporating operator overloads are passed to functions that did not have 
parameters type hinted but were not intend to be used with operator overloads 
resulting in subtle potential breakage. 

This argument is also consistent with the argument people had about not 
allowing default values to be generically used in calls to the function 
function. Their claim was that developers who did not write their code with the 
intention of exposing defaults should not have their defaults exposed. 
Similarly developers that do not write their code to enable operator overloads 
should not be used with  userland operator overloads unless they explicitly 
allow it, especially as they may not have have tested code with operator 
overloads.

Anyway, that is my two cents worth. 

TL;DR?  I argue that PHP should operator overloads but ONLY if there is a 
mechanism that requires the user of expressions that call overloaded operators 
to explicitly opt-in to their use.

-Mike

Reply via email to