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]