Re: [RFC] Operator Overrides -- Lite Edition

From: Date: Sat, 29 Jun 2024 09:05:20 +0000
Subject: Re: [RFC] Operator Overrides -- Lite Edition
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message


On Sat, Jun 29, 2024, at 11:01, Rob Landers wrote:
> 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:

sigh: not enough coffee again and I saw the blunder as soon as I sent it.. Here's the more
correct implementation.

class IntField {
  public function __construct(private int $max, int $value) {
    parent::construct($value, 10);
  }
  protected static 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 >= $left->max) return new IntField($left->max, $result % $left->max);
    return new IntField($left->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 long time ago now, I can say that there are non-communitive rings where
> having access to both "left" and "right" can allow you to handle this quite
> well.
> 
>>  
>>> 
>>>> 6. The comparable function you propose doesn't actually have an
>>>> operator it corresponds to. There is no operator in PHP for "is the left value comparable with
>>>> the right value". There are operators for comparisons themselves, which I assume you meant, but
>>>> a bool is insufficient as a return type for that.
>>> 
>>> In the engine, there’s just a compare function for internal overrides. So we just
>>> check that everyone agrees that the two objects are comparable and then pass it on to “business as
>>> usual.”
>> 
>>  I'm aware of how the compare handler for class entries and zend_compare interact.
>> What I am saying is that your design is insufficient for <=>. You cannot return
>> false from this method to mean uncomparable, and true to mean comparable.
>> The zend_compare function can validly return 0 or -1, with the -1 being used for both less than OR
>> greater than because the operands are reordered to always be a less than comparison. Then 1, which
>> normally is used for greater than, is used to mean uncomparable.
> 
> Ah, I mean that it calls this as a guard, before ever doing a comparison, not that this output
> will be used for comparison itself. This is deliberate, to keep it simple. If I get feedback that
> comparison should be implemented vs. a guard for comparison, I'd be happy to add it.
> 
>> As you are proposing this without any genuine expectation you can pass it, this will be the
>> last energy I will invest into helping.
> 
> I didn't mean it how I think you are taking it. To expand a bit on what I meant,
> "we" (as in people who want this feature, like myself) can only create RFCs for it. Maybe
> one day, the voters will change their mind, "we" will find an implementation they agree
> with, or they'll forget to vote "no" while enough people vote "yes." So,
> yes, I genuinely want this feature and I want to propose a feature that works and is the best I can
> come up with; at the same time, I don't expect it to pass, but I do hope that negative feedback
> will drive the feature to a compromise or solution that works. The only way to get there is by
> failing.
> 
> — Rob

— Rob


Thread (27 messages)

« previous php.internals (#124015) next »