Martin Nowak is officially MIA
sfp
sfp at hush.ai
Thu Mar 27 22:04:53 UTC 2025
On Thursday, 27 March 2025 at 20:25:52 UTC, Walter Bright wrote:
> On 3/18/2025 11:05 PM, Manu wrote:
>> I can't imagine any good reason his experiment should have
>> failed.
>
> My experience with C++ and Koenig lookup heavily influenced
> this.
>
> It looks nice in simple examples, but nobody stops with simple
> examples. Impenetrable code is the result.
>
> Operator overloading should be part of the type, not standalone
> coming from somewhere else.
I'd like to understand what impediment there is to having "free"
operator overloading.
It seems like once the code has been parsed/whatever, you should
have "canonicalized" the operator syntax into some function call.
At that point what difference does it make whether the operator
was defined as a free function or member function? Basically, why
would "UFCS" not also work for the canonicalized names for
overloaded operators?
I write mathematical software for a living and forcing operators
to be member functions sucks for me. This feature is important to
me, so I'll try to spell this out a little bit. I realize that my
opinion on its own doesn't carry a ton of weight; but, on the off
chance that the main reason this feature hasn't been implemented
is aesthetic rather than technical, I'd like to say my bit. ;-)
Main problem is that in mathematical software you want to be able
to implement symmetric operations, and oftentimes doing this
correctly requires double or multiple dispatch. The classic
example is a small linear algebra with specialized types for
different kinds of matrices.
Let's say I have a `DenseMatrix` type and a `SparseMatrix` type;
and, who knows, maybe an `IdentityMatrix` type. If I want to
implement a binary operation like matrix multiplication, it
really is nice to use operator overloading for this. Maybe the
best case scenario for the prospecting D user is doing something
like what Eigen (a C++ template linear algebra library) does and
lean on static polymorphism. But now I need to stick a separate
`opBinary!"*"` on each type. As the number of types grows this
gets significantly less maintainable. If I could define an
operator as a free function I could lean on D's amazing
metaprogramming capabilities and simplify my code, make it
shorter, more maintainable, etc, etc. And, speaking from my own
experience at least, this is not an insignificant or imagined
benefit.
Actually, whether static polymorphism and the whole Eigen concept
makes sense is totally debatable (at least for Eigen, the runtime
efficiency gained by expression templates is completely obviated
by the insane compile times... but this is a C++ library...). In
many cases runtime polymorphism may be preferable. Unfortunately,
D's `class` is straight out since it doesn't support multiple
dispatch. And, anyway, the same issue discussed in the previous
paragraph persists. A way to get around this is to use
metaprogramming and `struct` to build up bespoke "interface"
types that *do* support multiple dispatch (which is what I'm
doing... -_-), but... well, I'll just say this also runs into
trouble with non-free operator definitions.
A way around this problem that does work but isn't particularly
satisfying is to kiss operator overloading goodbye. Just use
`mul` for matrix multiplication. There's a good chance this is
what I'll end up having to do.
And, in fact, I've already done it for other mathematical
operations. I have a `ccomb(x, y, t)` function which computes the
convex combination `(1 - t)*x + t*y` for a wide variety of types
(standard types, arbitrary precision rationals, intervals,
vectors, whatever). Initially, I had this function defined in the
module of each type I wanted it defined for, but it ended up
being simpler and more natural to just define a new module
`ccomb.d` containing all those definitions... not unlike what is
done in MATLAB! The function `ccomb` is symmetric in `x` and `y`
and a good implementation of it also *wants* to be symmetric.
This symmetry would be extremely difficult to obtain if `ccomb`
were forced to be a member function.
Maybe you can see where I'm going with this... I don't see why
the functions defining operators should be treated any
differently!
More information about the Digitalmars-d
mailing list