On Wed, 5 Jan 2022 at 20:11, Jordan LeDoux <jordan.led...@gmail.com> wrote:
>
>
>
> On Wed, Jan 5, 2022 at 6:33 AM Andreas Hennings <andr...@dqxtech.net> wrote:
>>
>> Hello Jordan,
>> do you have any thoughts about these symmetric/left/right modifiers,
>> to get rid of the $operandPos parameter?
>>
>> To me, the parameter could be the kind of thing where in hindsight we
>> ask "why?".
>>
>> Also, can we drop the "public" modifier, if we do a new version of the RFC?
>>
>> Cheers
>> Andreas
>
>
> It's a totally different design concept (symmetric/left/right) and I've been 
> going over the design implications before I responded. For instance, wouldn't 
> this be a special case of method overloading? You're overloading according to 
> a modifier, not the typing, but there is that to contend with. If someone 
> defined `symmetric operator +` and `left operator +` which would be used? (My 
> feeling is left as its more specific.)

You would not be allowed to provide both on the same class.

A class can provide either no operator, or the left operator, or the
right operator, or both.
A "symmetric" operator is a shortcut to providing both left and right,
but using the same implementation.
A class with a "symmetric" operator cannot also have a "left" or
"right" version of the same operator - this would be the same as two
methods with the same name.
However, if the parent class has a "symmetric" operator, you _can_
override the "left" and/or "right" version in the subclass. In that
case, if the subclass provides "left", then the parent "symmetric"
implementation would only be used for the "right" direction.

I am writing "right" and "left" here, but perhaps "normal" and
"inverted" would be less ambiguous.
Also, perhaps instead of "symmetric" we could write "left right".

Perhaps this code will clarify:

class C {
  symmetric operator * (int $other) {..}
  # left operator * (int $other) {..} // -> Error, already defined.
  left operator - (int $other) {..}
  right operator - (int $other) {..}
  left operator / (float $other) {..}
  left operator % (D $other) {..}
}

class D {
  right operator % (C $other) {..}
}

(new C()) * 5; // -> symmetric operator *
5 * (new C());  // -> symmetric operator *
(new C()) - 5;  // -> left operator -
5 - (new C());  // -> right operator -
(new C()) / 5;  // -> left operator /
5 / (new C());  // -> Error, no operator provided.

(new C()) % (new D());  // -> left operator % provided by C.
(new D()) % (new C());  // -> Error, not supported.

This means, the "right operator" will only ever be called if the left
side does not provide a "left operator".

Basically this is not so different from your RFC.
Just instead of having to do a "if ($operandPos ===
OperandPosition::LeftSide) {..}" inside an implementation, we are
providing two separate implementations.


> How would they be stored within the zend_class_entry? Since they would 
> technically have the same name, something would need to happen for them to 
> not be in the function table.

The right and left version would need to be distinguished somehow internally.
I would say "left" is the default, and "right" has a modifier to its name.
Perhaps for symmetric operators, we could store two distinct entries
internally, if that makes things easier.

>
> The public modifier is not required (as stated in the RFC), you can just add 
> it if you want. Are you asking for `public operator` to produce a compile 
> error?

That would be the idea.
Perhaps others will disagree.
Allowing the "public" introduces a meaningless choice that people can
argue about in their code style, and have pointless git commits where
they add or remove the modifier based on preference.
Of course the same could be said about "public" in interface methods.

-- Andreas

>
> Jordan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to