Hi Johannes,
Thank you for your points! I think you point out some overlooked issues.
Johannes Schlüter wrote:
Which one is being called? - Vector's or Matrix's. How will your
vector know about my Matrix?
The way C++ solves this is by allowing non-member functions as
operators.
#include "vector3.h" // provides class Vector3
#include "matrix.h" // provides class Matrix, potentially
// from a different vendor
Matrix operator*(const Vector3 &lhs, const Matrix &rhs) {
// I can provide this myself if neither Vctor's nor
// Matrix's vendor do
return ...;
}
int main() {
Vector3 vec{...};
Matrix matrix{....};
// works
auto result = vec * matrix;
}
I wonder if it would be a good idea, if we do want operator overloading
in PHP, to implement a similar mechanism for this. Perhaps type-specific
overloads could be registered via some special function call or
declaration, something vaguely like:
class Vector {
public function __construct() {
php\register_overload($this, Matrix::class, '*', function ($a, $b) {
/* multiplication implementation here */
});
}
}
The engine could then do type-matching for you, and would implement
commutativity for you if the operator is commutative, so `$someVector *
$someMatrix` would call the above function, but so would `$someMatrix *
$someVector`. (Note: to support matrix multiplication, I guess
commutativity must be overridable. Also, I have forgotten whether
multiplying a matrix and a vector is commutative or not :p)
I think this approach would be less messy than having to implement full
type matching on both sides of a type pair, for a number of reasons:
* Instead of Vector having to have an implementation of __mul which
checks for Matrix, and Matrix having to have an implementation of __mul
which checks for Vector, just one of these types can call
register_overload with a single implementation (because the operation is
commutative).
* Whether two types can be used with a particular operator is clear:
either there is such a pair registered, or there is not, and PHP can
give appropriate error messages. It is unlikely there will be an issue
where one side has __mul but it just throws an exception or somethig.
Also, in a case like `$a * $b`, $a can implement support for $b without
$b having to support $a, while at the same time $b can implement support
for some unrelated other type, without `$b * $a` not working (with the
current proposal, imagine $a's __mul handler supporting $b but not
vice-versa).
* The engine can see conflicts (one class declares an overload involving
the other class, and vice-versa) and warn about them, rather than `$a *
$b` silently having completely different behaviour to `$b * $a`.
This is not to say we necessarily should implement this, but it may be
worth thinking about…
Thanks,
Andrea
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php