3 days ago
I'll let the PR and the followup PRs speak for themselves:

https://github.com/dlang/dmd/pull/14636
3 days ago
On 3/19/2025 6:16 AM, Manu wrote:
> Sorry Walter, I apologise.

Accepted. Thank you! -Walter

3 days ago
On 3/19/2025 8:36 AM, Meta wrote:
> (rightly so, IMO; a D compiler that prefers to import .h files over .d files in certain circumstances is just weird).

"Header" files are preferred over "Implementation" files.

3 days ago
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.

3 days ago
On 3/19/2025 6:20 AM, Ogion wrote:
> “With that power I should have power too great and terrible. And over me the Ring would gain a power still greater and more deadly.”

Koenig Lookup (officially known as ADL, Argument Dependent Lookup) is a terrible thing. Even Andrew Koenig was unhappy his name was associated with it.

I've seen the destruction that ADL hath wrought. It's similar to the horrors that macros inevitably spawn. Although hobbits are resistant to its evil influence, I haven't met any hobbitses yet. Just too many Boromirs.

D originally was not going to have operator overloading at all because of that, but eventually it was added, but heavily restricted compared with C++.
3 days ago
On 3/19/2025 6:18 AM, Guillaume Piolat wrote:
> Tsoding being able to work roughly like he's accustomed in C with a lot of familiarity, implementing his favourite pattern then modifying the compiler in less than 2 hours, is precisely because D isn't very prescriptive.

I'm pretty sure he worked out in advance the difficulties he'd encounter followed quickly by the solutions.

3 days ago
On 3/18/2025 7:32 PM, Lance Bachmeier wrote:
> There is too much negativity among D users for the most part. There are lots of problems, but that applies to every language.

What's important is can one code a solution quickly and it be more likely to work, be bug-free, and readable.

3 days ago
On 3/19/2025 12:47 AM, Manu wrote:
> I never want to see 8 different copies of a function because it's called with byte,ubyte,short,ushort,int,uint,long,ulong... where one opcode is different because it performed a different width sign-extension, and where the sign-extension should have been performed by the calling code anyway! Phobos is lousy with this sort of problem, and the binaries it produces are orders of magnitude bigger than they should be a lot of the time. Very aggressive optimisation might fix it, but it's basically just random chance as to whether optimisation will successfully collapse some insane code down to something appropriate or not.

I'm painfully aware of the template bloat.

Adam Wilson is in charge of Phobos 3. Let him know!
3 days ago

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!

3 days ago

On Thursday, 27 March 2025 at 20:01:41 UTC, Walter Bright wrote:

>

The reason is Iain didn't like it because he had file.d and file.h in the same directory.

This is not true.

>

Is this stupid? Yes.

I agree. Try to understand the problem and we can come up with a solution. I proposed one too.

But without understanding the problem you’ll never get traction.

-Steve