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