Hacker News new | ask | show | jobs
by usrbinenv 246 days ago
I really love D, it's one of my favorite languages. I've started implementing a vim-like text editor in it from scratch (using only Raylib as a dependency) and was surprised how far I was able to get and how good my test coverage was for it. My personal favorite features of D:

* unit tests anywhere, so I usually write my methods/functions with unit tests following them immediately

* blocks like version(unittest) {} makes it easy to exclude/include things that should only be compiled for testing

* enums, unions, asserts, contract programming are all great

I would say I didn't have to learn D much. Whatever I wanted to do with it, I would find in its docs or asked ChatGPT and there would always be a very nice way to do things.

2 comments

D is a bittersweet topic for me.

From a philosophical/language-design standpoint, it ticks so many boxes. It had the potential to be wildly popular, had a few things gone differently.

If the language tooling and library ecosystem were on par with the titans of today, like Rust/Go, it really would be a powerhouse language.

Isn't D supported by the GNU compiler collection? I personally would prefer this type of tooling over what Rust and Go do (I can't even get their compilers to run on my old platform anymore; not to mention all this dependencies on remote resources typical Rust/Go projects seem to have: which seems to be enforced by the ecosystem?)
It is, however keeping LDC and GCC up to date is a volunteer effort with not enough people, so they are always a bit behind dmd.

Still much better than GCCGO, kind of useless for anything beyond Go 1.18, no one is updating it any longer, and may as well join gcj.

LDC isn't regularly behind DMD lately. The issue lately has been more the release process with respect to DMD. People issues impacting that.
Which was my point, volunteer work without enough people.
Having written real code in D, I can say that the slight discrepancy between dmd, LDC, and gdc isn't a roadblock in practice.
Depends how creative you happen to be with some features.

For regular common code that is indeed not an issue.

It is supported. However on Windows GDC does not work. LDC based on LLVM needs Visual Studio but I maybe wrong since there are clang/llvm distributions based on mingw64. Other than that DMD works fine, a bit slower than the other compilers, but a charm to use.
Ldc like dmd ships lld and mingw import libraries and has for a few years now.

They both work out of the box without MSVC installed.

It's only ImportC feature that requires MSVC. The work required to get clang working in its place hasn't happened yet.

It is
Yeah, the foundations of the language are incredible. It's just everything else around it that brings it down (and is unfortunately very hard to motivate people to solve).

D definitely missed a critical period, but I love it all the same.

So, I also write Go and I don't get the part about tooling. I don't need formatters or linters as I'm adult enough to know how to format my code (in fact I dislike tools doing it for me). D also has dub, which is fine, as far as package managers go. The ecosystem is the only issue and Go does arguably have a lot of very cool libraries for virtually anything, but outside of webdev, I can't see myself using them. This is why D works a lot better for projects where I don't need all those dependencies and would do better without them.
I freely admit to not being a Go or Rust expert, but from what I can tell using C from D is even easier than in either of these languages. The C++ interop is also decently usable.

IMO, the bigger issue is language tooling.

D really does work as a "Better C" C compiler. For example, D's Import C supports this:

    void abc() { def(1.0); }
    void def(double) { }
I.e. forward references "just work". (Forward references don't work in C++, either.)
Being able to use ImportC to "just include" all of LAPACKE was a high point for me with this! Thanks for adding this feature, it rocks.

... Now, get started on ImportC++!!! (Only joking... kind of. ;-) )

If it makes you feel better I have some projects that I'm working on in order to improve the tooling. Would you mind listing out all of the things you think are missing, so I can work on those once I get the other ones done?
I like a lot about D. My main criticism of the language is that it quickly becomes too noisy as more of its nice features are used. I think this could be fixed, for example with better attribute defaults in function signatures, and I think Walter is aware of this.

I could tolerate the noisy language bits, but:

The standard library (Phobos) was so riddled with paper cuts that every day I used it felt like trying to navigate the surface of a coral reef... barefoot... in a hurricane... while blindfolded. It drove me off after a few months. (That was last year.)

A Phobos V3 design has begun, but given how few people they have to work on it, I am skeptical of it ever developing into a library that I would want to use. Here's hoping for a pleasant surprise. :)

You have any specific complaints about Phobos and a standard library you like?
A few examples from a little over a year ago:

Heavy reliance on the range interface, without automatic support for common range-like types like arrays, so calling code must be cluttered with wrappers.

Insistence on returning things exclusively as ranges, even when a single item is wanted, so calling code must be cluttered with dereferencing. (e.g. std.algorithm.searching.find)

The doubly-linked list implementation had no obvious way to remove a node by reference; removal of an inner item seemed to require traversing the list.

Inconsiderately designed class hierarchies. (e.g. InternetAddress & Internet6Address shared a base class that lacked a port field.)

Inconsiderately designed interfaces. (e.g. CRC32 could deliver a result only as a byte array, which fits the generic std.digest interface, but not as an integer, which is how 32-bit CRCs are often used in the real world.)

Unfortunate naming choices scattered about, such as a function name implying behavior subtly different from what the function does and a user probably expects (leading to surprising bugs) or named after a specific computer science algorithm instead of its purpose (making the needed operation hard to discover).

Various types and functions defined without the attributes required by other parts of the stdlib, or required in order to use/override them in safety-minded code. (e.g. nothrow, @safe, scope)

Time module lied about system clock resolution despite having internally retrieved the correct value from the OS.

Generally useful functionality kept private within the library, rather than made public, forcing users to either re-implement it themselves or lean on arcane trickery to get at it. (e.g. string escaping.)

Logger output customization was needlessly difficult.

No viable async/coroutine support. Vibe.d is the closest substitute, but is a third-party package, integrates poorly with Phobos, isn't documented very well, and is buggy.

...

Mind, these are just highlights of things I discovered while using D for one small project (a network protocol library and tool) so this is by no means a comprehensive account of problems in Phobos. All these problems could be worked around, but I ended up spending far too much time investigating them and developing workarounds instead of being productive.

I acknowledge that I was new to D, so some of my complaints might have had solutions. (However, I would point out that a solution that isn't easy to find might as well not exist.) Regardless, the pattern was clear: Phobos was a PITA to use. Too many paper cuts.

> a standard library you like?

I stuck with C, C++, and Python for more than a few years. Their standard libraries all have significant problems, but none frustrated me so much as to drive me away from the language.

The following statement originates from Adam Wilson who is heading the PhobosV3 project, and I will second it.

The issues you have are examples of known problems that PhobosV2 has suffered under. Coroutines, for instance we would like to have in language, a proposal (me, not Adam) have already made one, but it's sitting till next year. Naming and interfaces issues are a big part of what will change in PhobosV3.

If you introduce coroutines, please consider unifying them conceptually w/ generators (or better yet - ranges)
>Heavy reliance on the range interface, without automatic support for common range-like types like arrays, so calling code must be cluttered with wrappers.

But D arrays/slices are already ranges. Is this referring to string autodecoding or something else completely? I fail to recall any situations where builtin types required wrappers often.

>Insistence on returning things exclusively as ranges, even when a single item is wanted, so calling code must be cluttered with dereferencing. (e.g. std.algorithm.searching.find)

This is mirroring C++ iterator design and IMO the right move though I agree that specifically for ranges it is rather awkward to use in practice.

What would you return instead? A pointer? What if one wants to find the position of the element and do something after that with that position/subrange.

Thank you for this post. I can tell you that we do appreciate comments like this, and the deficiencies you cite are many of the reasons we are rewriting phobos and druntime.

The time module "lied" seems like a straight up bug. Can you give any more details on it?

https://issues.dlang.org/show_bug.cgi?id=24446

Thanks for responding well to constructive criticism.

Wow, this was introduced in 2012!

https://github.com/dlang/druntime/pull/88