Argumnentation against external function operator overloading is unconvincing

HaraldZealot via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 21 10:57:17 PDT 2016


In current D, overloading operator like "+" with external 
function is prohibited. There is the rationale [1] (see second 
paragraph).

BUT this rationale is totally UNCONVINCING. I can say that resume 
of rationale is: "it is impossible because it brakes some C++ 
patterns and behaviour". Further I will try to demonstrate such 
resume.

Let start with an example where external operator overloading can 
be useful. Imagine,  we want to create some lazy matrix algebra, 
where all operation return new object of corresponding to 
operation subtype. E.g. `transpose` returns `TransposedMatrix`, 
where `opIndex` just call `opIndex` of internally stored matrix 
with switched order of indices, `plus` returns `MatrixSum`, where 
`opIndex` just calculated the sum of two corresponding elements 
of stored matrices and so on. Of course we want that any 
resulting subtypes can interact with each other, so we require 
common "denominator". There are two ways compile-time duck-typing 
  with template bloating, or common interface (yeah, with garbage 
collection in the simplest implementation), but the last allows 
us to have some run-time parameters. So regard common interface 
approach: our interface should be minimal as possible, for our 
purposes having `rows`, `columns` and `opIndex` seems to be 
sufficient.
OK, we have:
```d
Matrix plus(Matrix A, Matrix B)
{
     final class MatrixSum : Matrix
     {...}
     ...
     return new MatrixSum(A, B);
}
...
C=plus(A, B);
```
(Or even `C=A.plus(B)` because of UFCS). And this works perfect.
If we want some sugar like `C=A+B` we are in trouble. We can 
create function `Matrix opBinary(string op)(Matrix A, Matrix B) 
if(op == "+")`, it even can be called with full name, but not 
with "+" operator, because now compiler just doesn't look for 
external function as overload for operator. If we want have this 
as member we should ad opBinary to our interface, what leads to 
some new trouble: now each type should have opBinary, but how we 
should implement this for example for `TransposedMatrix` or even 
more interesting (because of kind of type recursion) how we 
should implement it for `MatrixSum`. OK, me and Mathias Lang have 
found workaround for my particular case we should implement (and 
probably make `final`) opBinary for `Matrix` interface, which in 
its turn calls function `plus` we already described. But its 
create lines of code for nothing, because operators are 
considered as too exceptional.

Let us return to rationale.
First point is "Operator overloading can only be done with an 
argument as an object". Why??? it seems to come from "C++ mind", 
before UFCS was implemented in language. If we have `1.to!string` 
and `A.plus(B)` working, what wrong with `A+B` or `2*B` (where A 
and B matrices). Moreover for case like `2*B` (multiplication by 
scalar) we should have a bit ugly `opBinaryRight(string 
op)(double scalar)` as member function. It isn't convinced.

Second point is "Operator overloads USUALLY need access to 
private members of a class". It has nothing common with operator, 
it is only demonstrate  our C++ behave to work with private 
members in operator. But having access to private member isn't 
necessary for operator to work. In my example `plus` function 
uses only public API of my classes, it can be done such way in 
many, many cases. And also often this external function would be 
placed in the same module, so it is already have "friend" in such 
case. If external function in external module want to have access 
to private API, it is only a sign of bad design, and should be a 
problem of particular programmer how to rework the design, not 
case for compiler to step in. It isn't convinced.

Third point is totally unnecessary because we don't need access 
to private members.

So, no one of point convinces me.

What can really can convince me that rationale like: "if we do so 
total parsing algorithm will be corrupted, and we can't use D 
any-more", or at least "with that feature compiler becomes 100 
times slower".


So if someone has real rationale not to have operator overloading 
as external function I'm curios to arguments.


[1] http://dlang.org/rationale.html


More information about the Digitalmars-d mailing list