Re: [PHP-DEV] [RFC] Userspace operator overloading

  108622
February 16, 2020 14:13 jan.h.boehmer@gmx.de
> ) I know you're not alone in that feeling. If it turns out this is the majority view, I think it answers a couple of open questions:
> > Overload methods should definitely be named after operations, not symbols, to remind people they are implementing addition, not giving new meaning to +
> > They should probably be grouped into interfaces, which this RFC has so far resisted. How often does it make sense for a type to support addition but
not subtraction, or multiplication but not division? Even more clearly, if a type claims to implement bitwise OR but not bitwise AND, NOT, and XOR, something is
> definitely fishy. > > You can't stop people using overloading DSL-style, but you can make it obvious that it's not the intention of the feature (if we agree that it's
not the intention; maybe some people here are really hoping to use it that way?) On 16/02/2020 10:31, rowan.collins@gmail.com wrote: Except for simple numbers, almost no mathematical objects define division (only some special matrices can be on the right hand of a division, and for vectors there is no definition for division at all). Also think of time differences: $datetime1 - $datetime2 results in a DateInterval, but $datetime1 + $datetime2 is not a meaningful operation (Datetime already has a diff() method that do this). Also it is not really possible to split multiplicative and additive methods into different behavior, as when $a implements Additive Behavior it should be possible to do an -$a, but because of the the way PHP compiles the code this becomes -1*$a. This is sufficient for almost all cases, but it would require that the code also provides an possibility to handle multiplication. In my opinion this would lead to that even if an object implements these interfaces, in many cases you cannot be sure that it really supports all operations, which would contradict the whole idea of defining interfaces. I wonder if it would be reasonable to allow voting between an interface approach and the "separate magic function for each operator" approach... Greetings, Jan Böhmer
  108623
February 16, 2020 14:37 rowan.collins@gmail.com (Rowan Tommins)
On 16/02/2020 14:13, jan.h.boehmer@gmx.de wrote:
> Except for simple numbers, almost no mathematical objects define division > (only some special matrices can be on the right hand of a division, and for > vectors there is no definition for division at all).
Then my philosophical question would be: are those really the same operation as we have for integers and floats, or are they domain-specific meanings of the symbols? Vectors and matrices, for instance, have multiple types of "product"; does exactly one of them directly correspond to multiplication, or would * simply be overloaded with whichever named operation was most commonly used?
> Also think of time > differences: $datetime1 - $datetime2 results in a DateInterval, but > $datetime1 + $datetime2 is not a meaningful operation (Datetime already has > a diff() method that do this).
I'm not necessarily saying that the operations need to be symmetrical in allowed types and behaviour, but there is at least a meaning to both addition and subtraction in this case. And notably, DateTime + DateInterval and DateTime - DateInterval *are* a symmetrical pair.
> Also it is not really possible to split multiplicative and additive methods > into different behavior, as when $a implements Additive Behavior it should > be possible to do an -$a, but because of the the way PHP compiles the code > this becomes -1*$a.
That's a design decision; you could also treat it as equivalent to 0 - $a and call the subtraction overload.
> In my opinion this would lead to that even if an object implements these > interfaces, in many cases you cannot be sure that it really supports all > operations, which would contradict the whole idea of defining interfaces.
The value I see is not so much about checking the interface and assuming particular behaviour, but encouraging developers to use the feature in a certain way, if there is consensus that the feature is not intended for Domain-Specific Languages. Under the current RFC, I could write this: /**  * Class to represent a Unix command  */ class Command {     // ...     /**      * Implement $command1 | $command2      */     public static function __or(Command $first, Command $second): Command {         return $first->pipeOutputTo($second);     } } If the operations were grouped into interfaces, I would be forced to write this, making it much clearer that I am abusing the feature: /**  * Class to represent a Unix command  */ class Command implements BitwiseOperators {     // ...     /**      * Implement $command1 | $command2      */     public static function bitwiseOr(Command $first, Command $second): Command {         return $first->pipeOutputTo($second);     }     public static function bitwiseAnd(Command $first, Command $second) {         return PHP_OPERAND_TYPES_NOT_SUPPORTED;     }     public static function bitwiseXor(Command $first, Command $second) {         return PHP_OPERAND_TYPES_NOT_SUPPORTED;     }     public static function bitwiseNot(Command $operand) {         return PHP_OPERAND_TYPES_NOT_SUPPORTED;     }     public static function bitwiseShiftLeft(Command $operand, int $i) {         return PHP_OPERAND_TYPES_NOT_SUPPORTED;     }     public static function bitwiseShiftRight(Command $operand, int $i) {         return PHP_OPERAND_TYPES_NOT_SUPPORTED;     } } Regards, -- Rowan Tommins (né Collins) [IMSoP]