On Sat, Sep 14, 2024 at 11:51 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:
>
> 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?
>
> 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?
>
> 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, 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/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 this
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 = 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 = new PositiveInt(new PositiveInt(10) + 5);
```

Reply via email to