Re: [RFC] Operator Overrides -- Lite Edition

From: Date: Sat, 29 Jun 2024 09:01:21 +0000
Subject: Re: [RFC] Operator Overrides -- Lite Edition
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
On Sat, Jun 29, 2024, at 02:13, Jordan LeDoux wrote:
> 
> 
> On Fri, Jun 28, 2024 at 12:55 PM Rob Landers <[email protected]> wrote:
>> __
>> 
>> 
>>> 3. The private/protected distinction is fairly meaningless for the functions that
>>> implement overloads, because the privacy of the function is ignored completely when it is executed
>>> to evaluate an operator.
>> 
>> Hmm. I like the idea of protected, because it gives a structure to it that is apparent and
>> usable right from the IDE. You just “fill in the blanks” or stick with the default behavior. 
> 
> I do not understand how the visibility has any impact on the usability you are seeking to
> provide.

I guess it depends on what you mean by usability. From a technical standpoint, it has zero
usability, but from a dev-ex standpoint, it has a huge amount of usability.

If we add these as protected methods to the base class, I merely need to write "protected
static function<tab>" in my IDE and I will see all the methods I can write. It also lays
bare "how it works" for a PHP developer without any magic, making it easier to document.

> 
>>> 4. The static distinction is also fairly meaningless, as in PHP there is
>>> no situation possible where an operator overload can occur WITHOUT it operating on objects
>>> themselves.
>> 
>> For this, that is the wrong approach. The actual behavior is on the type, not the instance.
>> The object instances may not even know their value, they merely represent the value.
> 
> A GMP object instance that does not know its value? What are you even talking about? Can you
> show me some code explaining what you mean? I had literally months of this argument for the operator
> overloads RFC, and studied the overload implementations in six other languages as part of writing
> that RFC, I feel like I understand this topic fairly well. But I do not understand what you are
> saying here.

Heh, yeah, it's kinda weird. Let me explain. The GMP class hides its value in a
"private" member (because the value isn't actually a number, but a GMP resource), so
unless the programmer also sets the value to something they have access to, they won't know the
value (but they can always cast $this to a number or operate on it directly). The only way they
could get the value is to cast $this to float, which may lose some precision. The idea here is to
"write the rules" where the value doesn't matter, or if it does, embed that as part
of the rules.

For example, imagine we want to create a Field class, that takes a range for the field and keeps the
value in the field. It might look something like this:

class IntField {
  public function __construct(private int $max, int $value) {
    parent::construct($value, 10);
  }
  public function add($left, $right): self {
    // todo: guard that left can be added to right -- ie, both are integers
    $result = parent::add($left, $right);
    if ($result >= $this->max) return new IntField($this->max, $result % $this->max);
    return new IntField($this->max, $result);
  }
  // todo: remaining implementation
} 

I actually had a bit of a long-thought about it, and I think this is simpler (both to implement and
to use) than the traditional approach, and more powerful. With the more traditional approach, how do
define communitive rules? You are bound by traditional mathematics, more-or-less. From working in
cryptography, a