Re: [VOTE] User Defined Operator Overloads
| From: | Côme Chilliet | Date: | Tue, 04 Jan 2022 09:01:59 +0000 |
| Subject: | Re: [VOTE] User Defined Operator Overloads | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-116800@lists.php.net to get a copy of this message | ||
Hello,
From the RFC:
> If the left operand produces a TypeError due to the parameter types listed in the
> implementation, the operation is not retried with the right operand and the error is instead
> returned immediately. This is to help developers encounter errors in their program logic as early as
> possible.
This feels wrong if I understand correctly.
Let’s say I create a class A and I want to add support for "2 / new A()", which by
default does not work.
I can do
class A
{
operator /(int $other, OperandPosition $operandPos): mixed
{
return "example";
}
}
Now someone wants to build on my work, and add a class B that supports "new A() / new
B()".
class B
{
operator /(A $other, OperandPosition $operandPos): mixed
{
return "example";
}
}
This will not work because it will first try A->{'/'}(B) that throws a TypeError? So it
means what I was able to do for floats, cannot be done for my new classes afterwards? This is
inconsistent I think. It also means it is not possible to extend any existing class with operators
interacting with a new class, meaning you can only use operators among classes aware of each other,
most likely from the same package/library.
Also, this was stated already I think but I did not see an answer, from RFC example:
> class Matrix {
> public function __construct(readonly public array $value) {}
>
> public operator *(Matrix $other, OperandPosition $operandPos): Number
> {
> if ($operandPos == OperandPosition::LeftSide) {
> // Count of my columns needs to match
> // count of $other rows
> } else {
> // Count of my rows needs to match
> // count of $other columns
> }
> }
> }
The second branch of the if is dead code, as $matrix1 * $matrix2 will always call
$matrix1->{'*'}($matrix2, LeftSide) and never the other way around.
This means that $operandPos is useless in all cases where operators are only typed againts the same
type, and points to this design solution being wrong.
There is «Why not interfaces?» in the FAQ, does that mean that operators cannot be added in
interfaces? This is not stated clearly in the RFC.
Also, it is not clear if operator overload will affect comparison operations used in core functions
such as in_array, sort and so on.
Does implementing operator == allows using in_array to find an object in an array?
Which of these internal functions use == and which use ===, which is not overloadable?
Does implementing operator <=> allows sorting of arrays containing my objects?
Côme