I think that the left operand is the "owner", the magic method handler,
while the right operand is the argument.

So for $object * 5, we will have:

// $object instance
public function __multiply($number): self {
    return $this->multiply($number);
}

But for 5 * $object we will have an error. Call order should be respected
now once that will be impossible you have $objectA * $objectB without
defines a priority (the main handler).


--
Atenciosamente,
David Rodrigues


Em ter., 28 de jan. de 2020 às 20:14, <jan.h.boeh...@gmx.de> escreveu:

> Hello everybody,
>
>
>
> the last days I have experimented a bit with operator overloading in
> userspace classes (redefing the meaning of arithmetic operations like +, -,
> *, etc. for your own classes).
>
> This could be useful for different libraries which implements custom
> arithmetic objects (like money values, tensors, etc.) or things like
> Symfony
> string component (concatenate) operator, because it improves readability
> much:
>
> $x * ($a + $b) instead of $x->multiply($a->add($b))
>
>
>
> 4 years ago, there was a RFC about this topic (
> <https://wiki.php.net/rfc/operator-overloading>
> https://wiki.php.net/rfc/operator-overloading), which was discussed a bit
> (
> <https://externals.io/message/89967> https://externals.io/message/89967),
> but there was no real Outcome.
>
>
>
> I have tried to implement a proof of concept of the RFC, I encountered some
> problems, when implementing the operator functions as (non-static) class
> members and pass them only the “other” argument: What happens when we
> encounter an expression like 2/$a and how can the class differ this from
> $a/2. Also not every operation on every structure is e.g on commutative
> (e.g. for matrices A*B =/= B*A). So I tried a C#-like approach, where the
> operator implementations are static functions in the class, and both
> arguments are passed. In my PHP implementation this would look something
> like this:
>
>
>
> Class X {
>
>     public static function __add($lhs, $rhs) {
>
>                 //...
>
>    }
>
> }
>
>
>
> The class function can so decide what to do, based on both operands (so it
> can decide if the developer wrote 2/$a or $a/2). Also that way an
> implementor can not return $this by accident, which could lead to
> unintended
> side effect, if the result of the operation is somehow mutated.
>
>
>
> I have taken over the idea of defining a magic function for each operation
> (like Python does), because I think that way it is the clearest way to see,
> what operators a class implements (could be useful for static analysis).
> The
> downside to this approach is that this increases the number of magic
> functions highly (my PoC-code defines 13 additional magic functions, and
> the
> unary operators are missing yet), so some people in the original discussion
> suggest to define a single (magic) function, where the operator is passed,
> and the user code decides, what to do. Advantageous is very extensible
> (with
> the right parser implementation, you could even define your own new
> operators), with the cost that this method will become very complex for
> data
> structures which use multiple operators (large if-else or switch
> constructions, which delegate the logic to the appropriate functions). An
> other idea mentioned was to extract interfaces with common functionality
> (like Arithmetically, Comparable, etc.) like done with the ArrayAccess or
> Countable interfaces. The problem that I see here, is that this approach is
> rather unflexible and it would be difficult to extract really universal
> interfaces (e.g. vectors does not need a division (/) operation, but the
> concatenation . could be really useful for implementing dot product). This
> would lead to either that only parts of the interfaces are implemented (and
> the other just throw exceptions) or that the interfaces contain only one or
> two functions (so we would have many interfaces instead of magic functions
> in the end).
>
>
>
> On the topic which operators should be overloadable: My PoC-implementation
> has magic functions for the arithmetic operators (+, -, *, /, %, **),
> string
> concatenation (.), and bit operations (>>, <<, &, |, ^). Comparison and
> equality checks are implement using a common __compare() function, which
> acts like an overload of the spaceship operator. Based if -1, 0 or +1 is
> returned by the  comparison operators (<, >, <=, >=, ==) are evaluated. I
> think this way we can enforce, that the assumed standard logic (e.g
> !($a<$b)=($a>=$b) and ($a<$b)=($b>$a)) of comparison is implemented. Also I
> don’t think this would restrict real world applications much (if you have
> an
> example, where a separate definition of < and >= could be useful, please
> comment it).
>
> Unlike the original idea, I don’t think it should be possible to overwrite
> identity operator (===), because it should always be possible to check if
> two objects are really identical (also every case should be coverable by
> equality). The same applies to the logic operators (!, ||, &&), I think
> they
> should always work like intended (other languages like Python and C#
> handles
> it that way too).
>
> For the shorthand assignment operators like +=, -= the situation is a bit
> more complicated: On the one hand the user has learned that $a+=1 is just
> an
> abbreviation of $=$a+1, so this logic should apply to overloaded operators
> as well (in C# it is implemented like this). On the other hand it could be
> useful to differentiate between the two cases, so you can mutate the object
> itself (in the += case) instead of returning a new object instance (the
> class cannot know it is assigned to its own reference, when $a + 1 is
> called). Personally I don’t think that this would be a big problem, so my
> PoC-Code does not provide a possibility to override the short hand
> operators.) For the increment/decrement operators ($a++) it is similar, it
> would be nice if it would be possible to overload this operator but on the
> other hand the use cases of this operator is really limited besides integer
> incrementation and if you want to trigger something more complex, you
> should
> call a method, to make clear of your intent.
>
>
>
> On the topic in which order  the operators should be executed: Besides the
> normal priority (defined by PHP), my code checks if the element on the left
> side is an object and tries to call the appropriate magic function on it.
> If
> this is not possible the same is done for the right argument. This should
> cover the most of the use cases, except some cases: Consider a expression
> like $a / $b, where $a and $b has different classes (class A + class B). If
> class B knows how to divide class A, but class A does not know about class
> B, we encounter a problem when evaluating just from left to right (and
> check
> if the magic method exists). A solution for that would be that object $a
> can
> express that he does not know how to handle class B (e.g. by returning
> null,
> or throwing a special exception) and PHP can call the handler on object $b.
> I'm not sure how common this problem would be, so I don’t have an idea how
> useful this feature would be.
>
>
>
> My proof-of-concept implementation can be found here:
> <https://github.com/jbtronics/php-src>
> https://github.com/jbtronics/php-src
>
> Here you can find some basic demo code using it:
> <https://gist.github.com/jbtronics/ee6431e52c161ddd006f8bb7e4f5bcd6>
> https://gist.github.com/jbtronics/ee6431e52c161ddd006f8bb7e4f5bcd6
>
>
>
> I would be happy to hear some opinions for this concept, and the idea of
> overloadable operators in PHP in general.
>
>
>
> Thanks and Best regards,
>
> Jan Böhmer
>
>
>
>

Reply via email to