D Programming Language
dlang.org
dlang.org
But by including the GC/runtime it went into a category with C# and Java which are much better options if you're fine with shipping a runtime and GC. Eventually Go showed up to crowd out this space even further.
Meanwhile in the C/C++ replacement camp there was nothing credible until Rust showed up, and nowadays I think Zig is what D wanted to be with more momentum behind it.
Still kind of salty about the directions they took because we could have had a viable C++ alternative way earlier - I remember getting excited about the language a lifetime ago :D
As for "I think it would be move productive if you ...", that's just rude. I wasn't criticizing Fil-C, just pointing out an inaccuracy.
"That's just rude" - oh my, never though asking for evidence of a performance problem on HN would be "rude". And yes, if something is actually 5x slower, it's very likely a performance bug that can be fixed, as FillC's author has made it clear in several opportunities.
It's sad that people lie here. It's commonly recognized that programs run 1.5-5 times slower.
> if something is actually 5x slower, it's very likely a performance bug that can be fixed, as FillC's author has made it clear in several opportunities.
Another lie from someone who doesn't even know what the program is called.
Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters.
C# C interop is pretty smooth, Java is a different story. The fact that C# is becoming the GC language in game dev is proving my point.
>Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters.
Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision to fit into the use-cases they should have targeted from the start in my opinion.
Look D was an OK language but it had no corporate backing and there was no case where it was "the only good solution". If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better adoption.
True, but you still need to either generate or manually write the bindings. In D, you just import the C headers directly without depending on the bindings' maintainers.
> If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better
Any D compiler is literally also a C compiler. I sincerely don't know how can one be more C compatible than that.
> Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision
I think that it was more of an attempt to appease folks who won't use GC even with a gun to their head.
Meanwhile look at how popular Zig is getting 2 decades later. Why is that not D ? D also has comp-time and had it for over a decade I think ? Zig proves there's a need that D was in the perfect spot to fill if it did not make the GC decision - and we could have had 2 decades of software written in D instead of C++ :)
This is perfectly fair.
> D was in the perfect spot to fill if it did not make the GC decision
I just find it hard to believe that the GC is the one big wart that pushed everyone away from the language. To me, the GC combined with the full power of a systems language are the killer features that made me stick to D. The language is not perfect and has bad parts too, but I really don't see the GC as one of them.
regarding kitchen-sink-ness it's at least nowhere near as bad as C++, but that bar is basically below the ground anyway so it's not much to write home about.
You never get a second chance at making a good first impression.
I believe that many people that gladly use Rust or Zig or Go nowadays would be quite happy with D if they were willing to give it a fair evaluation. But I still often find people going "D? I would never use a language where the ecosystem is split between different standard libraries"/"D? No thanks, I prefer compilers that are open source" or similar outdated claims. These things have not been true for a long time, but once they are stuck in the heads of the people, it is over. And these claims spread to other people and get stuck there.
If you do not want to use a GC, it is trivial to avoid it and still be able to use a large chunk of the ecosystem. But often avoiding GC at all costs is not even necessary - you mostly want to avoid it in specific spots. Even many games today are written with tasteful usage of GC.
The one thing that really is a fair disadvantage for D is its small community. And the community is small because the community is too small (chicken/egg) and many believe in claims that have not been true for a long time ...
There's a good number of younger programmers like myself who've never heard of D, say, before 2017 when those false claims were still true. Our first impression of D comes from its state today, which is not that far behind from other emerging languages.
Respectfully, it doesn't prove your point. Unity is a commercial product that employed C# because they could sell it easily, not because it's the best language for game dev.
Godot supports C# because Microsoft sponsored the maintainers precisely on that condition.
Popularity is not proof of anything. C# is popular because it’s made by Microsoft and rode the OOP hype.
That is just the Unity effect. Godot adopted C# because they get paid to do so by Microsoft.
C# allows for far lees control over the garbage collection compared to D. The decision to use C# is partly responsible for the bad reputation of Unity games as it causes a lot of stutters when people are not very careful about how to manage the memory.
The creator of the Mono runtime actually calls using C# his Multi-million dollar mistake and instead works on swift bindings for Godot: https://www.youtube.com/watch?v=tzt36EGKEZo
sidenote, I wonder how many other low-level to high-level compilers exist out there. can't be many.
Allegedly some games are now managing to ship on console with ports of .NET NativeAOT.
Do you want GC? Great! Do not want GC? Well, you can turn it off, and lose access to most things. Do you want a borrow-checker? Great, D does that as well, though less wholeheartedly than Rust. Do you want a safer C/memory safety? There's the SafeD mode. And probably more that I forget.
I wonder if all these different (often incompatible) ways of using D ends up fragmenting the D ecosystem, and in turn make it that much harder for it to gain critical mass
My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm.
Nim kind of does that, too.
FWIW, I think "standing out" due to paradigm commitment is mostly downstream of "xyz-purity => fewer ways to do things => have to think/work more within the constraints given". This then begs various other important questions, of course.. E.g., do said constraints actually buy users things of value overcoming their costs, and if so for what user subpopulations? Most adoption is just hype-driven, though. Not claiming you said otherwise, but I also don't think the kind of standing out you're talking about correlates so well to marketing. E.g., browsers marketed Javascript (which few praised for its PLang properties in early versions).
The more positive phrasing would be that it is a very pragmatic language. And I really like this.
Currently opinionated langues are really in vogue. Yes they are easier to market but I have personally very soured on this approach now that I am a bit older.
There is not one right way to program. It is fun to use on opinionated language until you hit a problem that it doesn't cover very well and suddenly you are in a world of pain. I like languages that give me escape hatches. That allow me to program they way I want to.
What "most things" are these?
There's errdefer, which only defers if there was an error, but presumably you meant what you wrote, and not that.
BTW, D was the first language to have defer, invented by Andrei Alexandrescu who urged Walter Bright to add it to D 2.0 ... in D it's spelled scope(exit) = defer, scope(failure) = errdefer, and scope(success) which is only run if no error.
1. Runtime: A runtime is any code that is not a direct result of compiling the program's code (i.e. it is used across different programs) that is linked, either statically or dynamically, into the executable. I remember that when I learnt C in the eighties, the book said that C isn't just a language but a rich runtime. Rust also has a rich runtime. It's true that you can write Rust in a mode without a runtime, but then you can barely even use strings, and most Rust programs use the runtime. What's different about Java (in the way it's most commonly used) isn't that it has a runtime, but that it relies on a JIT compiler included in the runtime. A JIT has pros and cons, but they're not a general feature of "a runtime".
2. GC: A garbage collector is any mechanism that automatically reuses a heap object's memory after it becomes unreachable. The two classic GC designs, reference counting and tracing, date back to the sixties, and have evolved in different ways. E.g. in the eighties and nineties there were GC designs where the compiler could either infer a non-escaping object's lifetime and statically insert a `free` or have the language track lifetimes ("regions", 1994) and have the compiler statically insert a `free` based on information annotated in the language. On the other hand, in the eighties Andrew Appel famously showed that moving tracing collectors "can be faster than stack allocation". So different GCs employ different combination of static inference and dynamic information on object reachability to optimise for different things, such as footprint or throughput. There are tradeoffs between having a GC or not, and they also exist between Rust (GC) and Zig (no GC), e.g. around arenas, but most tradeoffs are among the different GC algorithms. Java, Go, and Rust use very different GCs with different tradeoffs.
So the problem with using the terms "runtime" and "GC" colloquially as they're used today is not so much that it differs from the literature, but that it misses what the actual tradeoffs are. We can talk about the pros and cons of linking a runtime statically or dynamically, we can talk about the pros and cons of AOT vs. JIT compilation, and we can talk about the pros and cost of a refcounting/"static" GC algorithm vs a moving tracing algorithm, but talking in general about having a GC/runtime or not, even if these things mean something specific in the colloquial usage, is not very useful because it doesn't express the most relevant properties.
Swift seems to require reference counting significantly more than Rust.
You see OP is trying to murk the waters when they claim C has a runtime. While there is a tiny amount of truth to that, in the sense that there’s some code you don’t write present at runtime, if that’s how you define runtime the term loses all meaning since even Assemblers insert code you don’t have to write yourself, like keeping track of offsets and so on. Languages like Java and D have a runtime that include lots of things you don’t call yourself, like GC obviously, but also many stdlib functions that are needed and you can’t remove because it may be used internally. That’s a huge difference from inserting some code like Rust and C do. To be fair, D does let you remove the runtime or even replace it. But it’s not easy by any means.
Except for the memory management literature, because it's interested in the actual tradeoffs of memory management. A compiler inferring lifetimes, either automatically for some objects or for most objects based on language annotations, has been part of GC research for decades now.
The distinction of working at compile time or runtime is far from huge. Working at compile time reduces the work associated with modifying the counters in a refcounting GC in many situations, but the bigger differences are between optimising for footprint or for throughput. When you mathematically model the amount of CPU spent on memory management and the heap size as functions of the allocation rate and live set size (residency), the big differences are not whether calling `free` is determined statically or not.
So you can call that GC (as is done in academic memory management research) or not (as is done in colloquial use), but that's not where the main distinction is. A refcounting algorithm, like that found in Rust's (and C++'s) runtime is such a classic GC that not calling it a GC is just confusing.
But is it not easy to opt out of in C, C++, Zig and Rust, by simply not using the types that use reference counting?
And how does your performance analysis consider techniques like arenas and allocating at startup only?
In C, Zig, and C++ sure. In Rust? Not without resorting to unsafe or to architectural changes.
> And how does your performance analysis consider techniques like arenas and allocating at startup only?
Allocating at startup only in itself doesn't say much because you may be allocating internally - or not. Arenas indeed make a big difference and share some performance behaviours with moving-tracing collectors, but they can practically only be used "as god intended" in Zig.
I should add that the JVM (and Go) also infers lifetime for non-escaping objects and "allocates" them in registers (which can spill to the stack; i.e. `new X()` in Java may or may not actually allocate anything in the heap). The point is that different GCs involve compiler-inferred lifetimes to varying degrees, and if there's a clear line between them is less the role of the compiler (although that's certainly an interesting detail) and more whether they generally optimise for footprint (immediate `free` when the object becomes unreachable) or throughput (compaction in a moving-tracing collector, with no notion of `free` at all).
There are also big differences between moving and non-moving tracing collectors (Go's concurrent mark & sweep and Java's now removed CMS collector). A CMS collector still has concepts that resemble malloc and free (such as free lists), but a moving one doesn't.
Look at C#'s competitive placings with C++/Rust on The Computer Benchmark game due to .NET's ruthless optimization.
And .NET is moving heavily into the AoT/pre-compilation direction for optimization reasons as well (source generators, AoT).
If you look at the change logs for the past few versions of the framework from perf perspective the most significant moves are : introduce new primitives to avoid allocating, move more logic to compile time, make AoT better and work with more frameworks.
A programming language having a GC doesn't mean every single allocation needs to be on the heap.
C# is finally at the sweet spot languages like Oberon, Modula-3 and Eiffel were on the late 90's, and unfortunely were overshadowed by Java's adoption.
Go and Swift (RC is a GC algorithm) are there as well.
D could be there as well on the mainstream, if there was a bit more steering into what they want to be, instead of having others catching up on its ideas.
That is what made me look into the language after getting Andrei Alexandrescu's book.
Note that even Rust's success, has triggered managed languages designers to research how far they can integrate linear, affine, effects, dependent types into their existing type systems, as how to combine the best of both worlds.
To the point that even Rust circles now there are those speaking about an higher level Rust that is supposed be more approachable.
Modern .NET isn't even difficult to avoid allocations, with the Span<T> API and the work they've done to minimize unnecessary copies/allocs within the std lib.
(I say this as a Kotlin/JVM dev who watches from the sideline, so not even the biggest .NET guy around here)
Yes, and that's where D is majorly superior to C# -- it's flexible enough for you to go down to the metal for the critical parts.
You are forgetting that a language with a less mature ecosystem isn't much help.
Yes, they added AOT but it's still challenging to do anything that requires calling into the OS, because you're going to need the bindings. It will still add some overhead under the hood and more overhead will you need to add yourself to convert the data to blittable types and back.
Mixing C# with other languages in the same project is also difficult because it only supports MSBuild.
> You are forgetting that a language with a less mature ecosystem isn't much help.
Fair.
Rust also has issues using anything besides cargo.
You don't. Any D compiler is a C compiler too, so it can take C headers without bindings or any overhead added.
Hint, before keeping to discuss what D can and cannot do, better go look how long I have been around on D forums, or existing projects on my Github.
Anything that has stable ABI does.
> go look how long I have been around on D forums
You claimed higher up in this thread that D requires bindings to interoperate with C API. You don't seem that well informed really.
D also has its own build system but it's not the only option. Meson officially supports building D sources. You could also easily integrate D with SCons, though there's no official support.
No, this is not true. You can invoke the compiler directly with no direct call to MSBuild what so ever.
Even using the dotnet command, which uses MSBuild under the hood, you are free to use your own build system. As an example - this code uses a Makefile to invoke the build: https://github.com/memsom/PSPDNA
If you want to call csc directly, it will compile with args just fine. And, if you have a working C# compiler on you platform, whether or not it uses MSBuild behind the scenes is kind of inconsequential.
You may also directly call the msbuild command, and it more or less does the same thing as the dotnet command, but hardly anyone eve calls msbuild directly these days.
Not to mention that writing a high quality GC is a monumental task - it took those decades for C# and Java to get decent - very few projects have the kind of backing to pull that off successfully.
In practical terms think about the complexity of enabling WASM that someone mentioned in this thread when you reuse C runtime and skip tracing GC.
I'm kind of venting in the thread to be fair, Walter Bright owes me nothing and it's his project, I had fun playing with it. I'm just sad we couldn't have gotten to Zig 20 years ago when we were that close :)
1. Very load overhead calling of native libraries. Wrapping native libraries from Java using JNI requires quite a bit of complex code, configuring the build system, and the overhead of the calls. So, most projects only use libraries written in a JVM-language -- the integration is not nearly as widespread as seen in the Python world. The Foreign Function and Memory (FFM) API is supposed to make this a lot easier and faster. We'll see if projects start to integrate native libraries more frequently. My understanding is that foreign function calls in Go are also expensive.
2. Doesn't require a VM. Java and C# require a VM. D (like Go) generate native binaries.
As such, D is a really great choice when you need to write glue code around native libraries. D makes it easy, the calls are low overhead, and there isn't much need for data marshaling and un-marshaling because the data type representations are consistent. D has lower cognitive overhead, more guardrails (which are useful when quickly prototyping code), and a faster / more convenient compile-debug loop, especially wrt to C++ templates versus D generics.
2. Java and C# can also generate native binaries, just like Go, no need for VM.
3. C++ nowadays has concepts, modules and compile time execution
This wasn't true in 2010, but D has let them catch up with missing features.
There were several vendors selling AOT compilers for embedded systems, nowadays they are concentrated into two vendors, PTC and Aicas.
Then you have the free beer compilers GraalVM and OpenJ9, which are basically the reason why companies like Excelsior JET ended up closing shop.
Also .NET has had many flavours, starting with NGEN, Mono AOT, Bartok, MDIL, .NET Native, and nowadays Native AOT.
Both ecosystems are similar to Lisp/Scheme nowadays, having a mix of JIT and AOT toolchains, each with its plus and minus, allowing the developers to pick and choose the best approach for their deployment scenario.
On #2, I generally reach for either TS/JS with Deno if I need a bit more than a shell script, or Rust for more demanding things. I like C# okay for the work stuff that I do currently though.
But I think Walter quite like what D is today.
Are there technical reasons that Rust took off and D didn't?
What are some advantages of D over Rust (and vice versa)?
Many of us believe on automatic memory management for systems programming, having used quite a few in such scenarios, so that is already one thing that D does better than Rust.
There is the GC phobia, mostly by folks that don't get not all GCs were born alike, and just like you need to pick and chose your malloc()/free() implementation depending on the scenario, there are many ways to implement a GC, and having a GC doesn't preclude having value types, stack and global memory segment allocation.
D has compile time reflection, and compile time metaprogramming is much easier to use than Rust macros, and it does compile time execution as well.
And the compile times! It is like using Turbo Pascal, Delphi,... even thought the language is like C++ in capabilities. Yet another proof complexity doesn't imply slow compile natives in a native systems language.
For me, C# and Swift replace the tasks at work were I in the past could have reached for D instead, mostly due to who is behind those languages, and I don't want to be that guy that leaves and is the one that knew the stack.
The problem is the term "systems programming". For some, it's kernels and device drivers. For some, it's embedded real-time systems. For some, it's databases, game engines, compilers, language run-times, whatever.
There is no GC that could possibly handle all these use-cases.
Right now, you'd have to switch languages.
But in a Great Language you'd just have to refactor some code.
Take C - you can either manually manage your memory with malloc() and free(), or you can #include a GC library (-lgc is probably already on your system), and use GC_malloc() instead. Or possibly mix and match, if you're bold and have specific needs.
And if ever some new revolutionary GC method is developed, you can just replace your #include. Cutting-edge automatic memory management forever.
People forget there isn't ONE GC, rather several of possible implementations depending on the use case.
Java Real-Time GC implementations are quite capable to power weapon targeting systems in the battlefield, where a failure causes the wrong side to die.
> Aonix PERC Ultra Virtual Machine supports Lockheed Martin's Java components in Aegis Weapon System aboard guided missile cruiser USS Bunker Hill
https://www.militaryaerospace.com/computers/article/16724324...
> Thales Air Systems Selects Aonix PERC Ultra For Java Execution on Ground Radar Systems
https://vita.militaryembedded.com/5922-thales-execution-grou...
Aonix is nowadays owned by PTC, and there are other companies in the field offering similar implementations.
(Also, what's with this stupid "hater" thing, it's garbage collection we're talking about, not war crimes)
It isn't stupid, it is the reality of how many behave for decades.
Thankfully, that issue has been slowly sorting out throughout generation replacement.
I already enjoy that nowadays we already have reached a point in some platforms where the old ways are nowadays quite constrained to a few scenarios and that's it.
D retains object-oriented programming but also allows functional programming, while Rust seems to be specifically designed for functional programming and does not allow OOP in the conventional sense.
I've been working with D for a couple of months now and I noticed that it's almost a no-brainer to port C/C++ code to D because it mostly builds on the same semantics. With Rust, porting a piece of code may often require rethinking the whole thing from scratch.
Is this a Walter Bright alt? I've seen him use the cowboy programmer term a few times on the forum before.
https://groups.google.com/g/comp.lang.lisp/c/tfzX3Sq96Xk/m/0...
1. D had a split similar to python 2 vs 3 early on with having the garbage collector or not (and therefor effectively 2 standard libraries), but unlike python it didn't already have a massive community that was willing to suffer through it.
2. It didn't really have any big backing. Rust having Mozilla backing it for integration with Firefox makes a pretty big difference.
3. D wasn't different enough, it felt much more "this is c++ done better" than it's own language, but unlike c++ where it's mostly a superset of c you couldn't do "c with classes" style migrations
Yes. D tried to jump on the "systems programming with garbage collection" dead horse, with predictable results.
(People who want that sort of stupidity already have Go and Java, they don't need D.)
I don't even know what that term means anymore; but afaik Java didn't really have reliable low-level APIs until recently.
Go wasn't around when D was created, and Java was an unbelievable memory hog, with execution speeds that could only be described as "glacial".
As an example, using my 2001 desktop, the `ls` program at the time was a few kb, needed about the same in runtime RAM and started up and completed execution in under 100ms.
The almost equivalent Java program I wrote in 2001 to list files (with `ls` options) took over 5s just to start up and chewed through about 16MB of RAM (around 1/4 of my system's RAM).
Java was a non-starter at the time D came out - the difference in execution speed between C++ systems programs and Java systems programs felt, to me (i.e. my perception), larger than the current difference in performance between C++/C/Rust programs and Bash shell scripts.
Of course you can make codegen as part of your build process with any language, but that can be kludgy (and often limited to a single project).
auto is used as a return type because it's easy, and in some cases because the type is defined internally in the function and can't be named.
You would not like the code that uses auto everywhere if you had to type everything out, think range wrappers that are 5 levels deep.
Real compile-time reflection is in the works; the very earliest stages of a prototype implementation were released to the nightly channel last month (https://github.com/rust-lang/rust/pull/146923), and the project has proposed (and is likely to adopt) the goal of completing that prototype implementation this year (https://rust-lang.github.io/rust-project-goals/2026/reflecti...), though it most likely will not reach the stable channel until later than that, since there are a whole lot of complicated design questions that have to be considered very carefully.
Using serde_json to accurately model existing JSON schemas is a pain because of it.
I personally find third-party deriving macros in Rust too clunky to use as soon as you need extra attributes.
My (somewhat outdated) experience is that D feels like a better and more elegant C++. Rust certainly has been influenced by C and C++, but it also took a lot of inspiration from the ML-family of languages and it has a much stronger type system as a consequence.
As someone who considered it back then when it actually stood a chance to become the next big thing, from what I remember, the whole ecosystem was just too confusing and simply didn't look stable and reliable enough to build upon long-term. A few examples:
* The compiler situation: The official compiler was not yet FOSS and other compilers were not available or at least not usable. Switch to FOSS happened way too late and GCC support took too long to mature.
* This whole D version 1 vs version 2 thingy
* This whole Phobos vs Tango standard library thingy
* This whole GC vs no-GC thingy
This is not a judgement on D itself or its governance. I always thought it's a very nice language and the project simply lacked man-power and commercial backing to overcome the magical barrier of wide adoption. There was some excitement when Facebook picked it up, but unfortunately, it seems it didn't really stick.
FOSS: DMD was always open source, but the backend license was not compatible with FOSS until about 2017. D is now officially part of GCC (as of v6 I think?), and even the frontend for D in gcc is written in D (and actively maintained).
D1 vs. D2: D2 introduced immutability and vastly superior metaprogramming system. But had incompatibilities with D1. Companies like sociomantic that standardized on D1 were left with a hard problem to solve.
Tango vs phobos: This was a case of an alternative standard library with an alternative runtime. Programs that wanted to use tango and phobos-based libraries could not. This is what prompted druntime, which is tango's runtime split out and made compatible, adopted by D2. Unforutuntately, tango took a long time to port to D2 and the maintainers went elsewhere.
gc vs. nogc: The language sometimes adds calls to the gc without obvious invokations of it (e.g. allocating a closure or setting the length of an array). You can write code with @nogc as a function attribute, and it will ban all uses of the gc, even compiler-generated ones. This severely limits the runtime features you can use, so it makes the language a lot more difficult to work with. But some people insist on it because it helps avoid any GC pauses when you can't take it. There are those who think the whole std lib should be nogc, to maximize utility, but we are not going in that direction.
And I am here, enjoying both. Life is good.
I think people forget this. I know a lot of folks that looked at D back when it needed to win mindshare to compete with the currently en vogue alternatives, and every one of them nope'd out on the licensing. By the time they FOSS'ed it, they'd all made decisions for the alternative, and here we are.
Rust has some of the functional programming niceties like algebraic data types and that's something lacking in D.
This talk explain why, it's not technical: https://www.youtube.com/watch?v=XZ3w_jec1v8
> What are some advantages of D over Rust (and vice versa)?
Advantages for D: Build faster, in typical programs you would need about 20 packages not 100, COM objects, easy meta-programming, 3 compilers. GC, way better at scripting.
Advantages for Rust: borrow-checker is better. rustup.
Really good talk, I remember watching it when it came out. Elm is what got me looking into FP several years ago, a nice language it was.
After all, D is supported by GCC and Clang and continually being maintained, and if updates stopped coming at some point in the future, anyone who knew a bit of C / Java / insert language here could easily port it to their language of choice.
Meanwhile, its syntax is more expressive than many other compiled languages, the library is feature-rich and fairly tidy, and for me it's been a joy to use.
The team is quite small and mostly volunteers, so there is the question how long can Walter Bright keep at it, and who will keep it going afterwards when he passes the torch.
It is true we have a small team. But we are a dedicated team.
So uh, funny story: I didn’t know this a few years back. GDC was missing the sqlite interface in GDC’s phobos. This made it so the dlang onedrive client and some other packages wouldn’t compile with it. Situation was like this for years: https://forum.dlang.org/thread/doevjetmiwxovecplksr@forum.dl...
I eventually complained that it was easier to argue with Walter about politics on HN than get a library fixed on his programming language. Fortunately the right people saw it and it was fixed soon after: https://bugs.gentoo.org/722094
I had read about the split (D vs. OpenD) recently on the Dlang newsgroup.
Also, just had the thought that the split may damage Dlang's progress / prospects, for users, like the Phobos issue etc. stuff was supposed to have done.
I don't know much about those details either, I had just read a bit about it earlier, as an interested light user of the language.
A language with sane Compile Time features (Type Introspection, CTFE, mixins, etc)
A language that can embrace C ecosystem with sane diagnostics
A language that ships with its own optimizing code generator and inline assembler!
A compiler that compiles code VERY fast
A compiler with a readable source code that bootstraps itself in just 5 seconds
People who dunk on it "bEcAuSe iT Is nOt MaInsTrEaM" are clueless
fwiw nbody.dlang 2005
https://salsa.debian.org/benchmarksgame-team/archive-alioth-...
Like 20 years ago:
https://web.archive.org/web/20060525101747/http://shootout.a...
Also, this presentation https://accu.org/conf-docs/PDFs_2007/Alexandrescu-Choose_You... killed a lot of bike shedding!
At the same time, I've never used it, I'm not sure why.
Anyway, the author of D language is here on HN (Walter Bright).
Maybe people should instead talk about how they use D or what they'd like to see added to D? In an attempt to be the change one wants to see, I'd say named arguments are a real win and there seem to be some stalled proposals for that in D last I checked.
That "one thing" could be real or propaganda. Rust's one thing is writing "memory-safe" without GC. Eventually the marginal cost becomes too high or your are tricked by advertising and "graduate" from awk to perl. From there depending on the pull of the community or the actual utility of the language you will use it for more and more tasks. If the community pull is strong your programs start to look like line noise or boilerplate hell. If the utility for your problems is genuine they remain simple but you probably aren't producing the most efficient binaries.
As for why c programmers don't just use -betterc well some do, but for most people the reality is that can just do it in c and prefer c -> c++ (ofc the vast majority of projects just start as c++ which makes -betterC )
c++'s one thing c with objects.
If you learned to code writing Go what did you do?
If you learned to code writing D what did you do?
That's not to say you can't learn to code from writing D just that it discipline, most people don't even know a problem exists before they are already learning some language or tool, nor do they have the goal of building everything, most programmers are lazy they want to build the minimal amount and end up building everything by accident.
Why don't experienced devs use D then? They think if they strive for ideological purity that they won't "build everything" next time, or they just enjoy ideological purity as it's own mental exercises. Unix faithfuls want to show that computing can be (conceptually) simple in implementation and use. Rust programmers want to show that those simple (to use) unix programs can be (memory) safe. To a senior engineer D is just too good and easy to take.
Say your starting a new Staff Engineer or Tech Lead job. What gets you to convince a CTO that we need to have a team learn D ?
On the flip side, where are the 200k base salary D positions.
Get me an interview in 2 months and I'll drop 10 hours a week into learning
Apple is all in on Swift, so you will not be writing native MacOS or iOS code for UI in D, best case you put your business logic in D but you can do that in any language which has bindings to swift/Obj-C.
Android is all in on Kotlin/Java, not D again
Microsoft is all in on C#, again not D.
Linux your two best options for UI is GTK and Qt, C and C++ respectively.
So the only place where you could bave seemless integration is Linux through FFI.
Here's the thing though, for building a core layer that you can wrap a UI around, Rust has insanely good ergonomics, with very good third-party libraries to automatically generate safe bindings to a decent amount of languages, at least all those listed above and WASM for web.
None of those uses cases are painless in D.
It makes sense for a complex productivity app (e.g. an office suite editor) to implement the UI from scratch anyway, and for that they may choose D. If Jane Street didn't pick OCaml, it would've died long ago -- in the same manner, some company might pick D to do UI or anything else really.
Handling energy efficiency/a11y/i8n is non trivial in any language, using the paved road of the system's native implementation solves for many of those problems out of the box.
You would need to reimplement all of that in D lang for your UI layer, and all you wanted to do was build an application to solve a problem, you weren't in the business of building a UI library to begin with.
You're free to start a company and solve a real business problem.
If I became a D expert tomorrow it's not going to make me more money. It's not getting me a better job.
The latest release [1] was on Jan 7th, and it contains more updates than, say, the latest release of Dart, which has one of the largest corporations behind it.
> This very post is probably his too, under an alt :)
The probability of that is virtually zero. Walter is a principled person, has better things to do, and his writing style is vastly different from the OP's.
I would be happy if they released it without phobos.
Other than that it is excellent.
DMD does its job.
Ownership and borrowing are so much less baroque in D than in Rust. And compile times are superb.
In a better world, we would all be using D instead of C, C++ or Rust.
However in this age of Kali...
I agree with the sentiment, I really like D and find a missing opportunity that it wasn't taken off regarding adoption.
Most of what made D special in D is nowadays partially available in mainstream languages, making the adoption speech even harder, and lack of LLM training data doesn't help either.
That shouldn't stop any self-respecting programmer.
Enterprise CMS deployment projects have already dropped amount of assets teams, translators, integration teams, backend devs, replaced by a mix of AI, SaaS and iPaaS tools.
Now the teams are a fraction of the size they used to be like five years ago.
Fear not, there will be always a place for the few ones that can invert a tree, calculate how many golf balls fit into a plane, and are elected to work at the AI dungeons as the new druids.
The irony in this statement is hilarious, and perfectly sums up the reality of the situation IMO.
For anyone who doesn't understand the irony: a carpenter is someone who makes things like houses, out of wood. They absolutely still fucking exist.
Industrialised furniture such as IKEA sells has reduced the reliance on a workforce of cabinet makers - people who make furniture using joinery.
Now if you want to go ask a carpenter to make you a table he can probably make one, but it's going to look like construction lumber nailed together. Which is also quite a coincidence when you consider the results of asking spicy autocomplete to do anything more complex than auto-complete a half-written line of code.
I think _you_ have misunderstood what a carpenter is. At least where I live, you might get a carpenter to erect the wood framing for a house. Or build a wooden staircase. Or erect a drywall. I'm sure most carpenters worth their salt could plausibly also make wooden furniture, at an exorbitant cost, but it's not at all what they do.
I sanity checked with Wiktionary, and it agrees: "A person skilled at carpentry, the trade of cutting and joining timber in order to construct buildings or other structures."
a person whose job is making and repairing wooden objects and structures
Carpenters make many things besides houses.
See the section "Types of carpentry".
I'm sorry, what? Are you suggesting that Ikea made carpenters obsolete? It's been less than 6 months since last I had a professional carpenter do work in my house. He seemed very real. And charged very real prices. This despite the fact that I've got lots of Ikea stuff.
Which is it? Carpenters or furniture makers? Because the two have nothing in common beyond the fact that both professions primarily work with wood. The former has been unaffected by automation – or even might plausibly have more demand due to the overall economic activity caused by automation! The latter certainly has been greatly affected.
The fact that people all over the thread are mixing up the two is mindboggling. Is there a language issue or something?
Those that learn to do robot maintenance, are the ones left at the factory.
Which the discussion seems to imply it kind of works, but not without a few pain points.
It's not like it knows perfect D, it does make mistakes and I don't work on a C++ or Rust project to compare its behavior. Generating templates from scratch is a bit of a challenge but given we have plenty of examples in our code with some prodding it manages to write well enough.
I actually think that the average D code produced has been superior to the code produced for the C++ problems I tested. This may be an outlier (the problems are quite different), but the quality issues I saw on the C++ side came partially from the ease in which the language enables incompatible use of different features to achieve similar goals (e.g. smart_ptr s new/delete).
They can.
Pointers are not the only 'pointer's to resources. You can have handles specific to your codebase or system, you can have indices to objects in some flat array that the rest of your codebase uses, even temporary file names.
An object oriented (or 'multi paradigm') language has to account for these and not just literal pointers.
This is handled reasonably well both in Rust and C++. (In the spirit of avoiding yet another C++ vs Rust flamewar here, yes the semantics are different, no it doesn not make sense for C++ to adopt Rust semantics)
struct resource {
resource(ctx *c, ...) {index = c->store(...); ...;}
size_t index;
ctx *c;
~resource() {c->free(index);}
// copy constructor+op creates new handle
// move constructor+op copies the handle, maybe zeroes the current one
};
With this you can rely on RAII, smart pointers, upcoming lifetime checks and annotations, etc. The core idea is that you treat objects of classes like this as values and everything works out seamlessly. Even if they are 'pointers' in all but name. You can also overload the dereference operator for it to have pointer-like syntax, but that is discouraged.When you have just once resource this might be overkill but for large projects with tangled webs of resources, this sort of setup really makes the code simpler and easier to design.
That's C++ for you, simple things look complex but once you get into big hairy projects things stay at the same level of complexity instead of becoming an unmanageable mess.
D almost supports RAII, and the compiler seems to do some automated copy to move conversion, but this is the sort of thing that really, really needs a large number of users and compiler implementers to iron out issues and corner cases. Nothing against D, the language is pretty neat!
No, it is abstracted away. You just have to follow best practices when writing a library.
resource foo(...); // This gets freed at the end of scope. See RAII.
auto x = make_unique<resource>(...); // can be moved, freed when owner is.
auto y = make_shared<resource>(...); // freed on zero reference countThe reason for that is OOP tends to favor constructs where each objects holds references to other objects, creating whole graphs, its not uncommon that from a single object, hundreds of others can be traversed.
Even something so simple as calling a member function from a member function becomes incredibly difficult to handle.
Tbh - this is with good reason, one of the biggest flaws of OOP is that if x.foo() calls x.bar() in the middle, x.bar() can clobber a lot of local state, and result in code that's very difficult to reason about, both for the compiler and the programmer.
And it's a simple case, OOP offers tons of tools to make the programmers job even more difficult - virtual methods, object chains with callbacks, etc. It's just not a clean programming style.
Edit: Just to make it clear, I am not pointing out these problems, to sell you or even imply that I have the solution. I'm not saying programming style X is better.
When commandline apps were everywhere, people dreamed of graphical interfaces. Burdened by having to also do jobs that it was bad at, the commandline got a bad reputation. It took the dominance of the desktop for commandline apps to find their niche.
In a similar way, OOP is cursed by its popularity. It has to become part of a mixed diet so that people can put it where it has advantages, and it does have advantages.
In diehard FP (e.g. Haskell) it's hard to even place a breakpoint, let alone see the complete state. In many cases, where implementing a piece of logic without carrying a lot of state is impossible, functional programming can also become very confusing. This is especially true when introducing certain theoretical concepts that facilitate working with IO and state, such as Monad Transformers.
Imho, most FP languages have very serious human-interface issues.
It's no accident that C likes statements (and not too complex ones at that). You can read and parse a statement atomically, which makes the code much easier to read.
In contrast, FP tends to be very, very dense, or even worse, have a density that's super inconsistent.
Depends on the FP. Pipes make things fairly legible. Example from Elixir:
def some_function(thing, doodad, doohickey) do
thing
|> foo(doodad)
|> bar()
|> baz(doohickey)
|> quux()
end
Also easy to debug -- break on any of those lines, or insert `|> IO.inspect()` at any point for good old fashioned print debugging.Conversely, the non-FP non-pipe version of this would:
(a) be monstrous and difficult to segment: `quux(baz(bar(foo(thing, doodad)), doohickey))`,
(b) needlessly require OOP: `thing.swizzle(doodad).razzle().blorple(doohickey).dazzle()`, where the functions are methods defined on the preceding construct (or some parent construct, to god-knows-what generation), or
(c) require a lot of throw away variables (you get the picture).
I wish more languages had a pipe construct. It's very handy.
Interestingly, D is one of the few languages to have uniform function call syntax,[0] which makes the dot syntax effectively act as a pipe operator, requiring no OOP coupling for its use. Very neat!
[0] https://en.wikipedia.org/wiki/Uniform_function_call_syntax
I have ported Ray Tracing in One Weekend into Rust, while keeping the same OOP design from the tutorial, and affine types were not an impediment to interfaces, polymorphism and dynamic dispatch.
The whole concept of OOP is a major conceptual regression in how it treats aliasing, which is a major headache for compiler writers, necessitating either whole program analysis or JIT like techniques.
That's more a problem of having mutable references, you'd have the same problem in a procedural language.
In fact I don't even know of any production language that handles variable mutability with any rigor other than Rust.
https://www.youtube.com/playlist?list=PLpM-Dvs8t0VZn81xEz6Ng...
Never has an old language gained traction, its all about the initial network effects created by excitement.
No matter how much better it is from C now, C is slowly losing traction and its potential replacements already have up and running communities (Rust, zig etc)
But the real explosion happened with ML.
At the time Java was the mature but boring "enterprise" alternative to both, but also beginning its decline in web mindshare as Ruby/Python (then JavaScript/Node) were seen as solving much of the verbosity/complexity associated with Java.
There was a lot of worry that the Python 2->3 controversy was threatening to hurt its adoption, but that concern came from Python in a position of strength/growing fast.
Python's latter day positioning as the ML/scientific computing language of choice came as its position in the web was being gobbled up by JavaScript by the day and was by then well on the downswing for web, for a variety of technical/aesthetic reasons but also just simply no longer being "cool" vs. a Node/NoSQL stack.
For example, python got a similar boost in popularity in the late 2000s and early 2010s when almost every startup was either ruby on rails or django. Then again in the mid 2010s when "data science" got popular with pandas. Then again in the end of 2010s with ML. Then again in the 2020s with LLMs. Every time people eventually drop it for something else. It's arguably in a much better place with types, asyncio, and much better ecosystem in general these days than it was back then. As someone who worked on developer tools and devops for most of the time, I always dread dealing with python developers though tbh.
Out of curiosity, why is that?
Containers have certainly helped a lot with python deployments these days, even if the Python community was late to adopt it for some reason. throughout the 2010s where containers would have provided a much better story especially for python where most libraries are just C wrappers and you must pip install on the same target environments, python developers I dealt with were all very dismissive of it and just wanted to upload a zip or tarball because “python is cross platform. It shouldn’t matter” then we had to invent all sorts of workarounds to make sure we have hundreds of random system libs installed because who knows what they are using and what pip will need to build their things. prebuilt wheels were a lot less common back then too causing pip installs to be very resource intensive, slow and flaky because som system lib is missing or was updated. Still python application docker images always range in the 10s of GBs
I started using Python in version 1.6, there were already several O'Reilly books, and Dr.Dobbs issues dedicated to Python.
Also, many languages that see a lot of hype initially lose most of their admirers in the long run, e.g. Scala.
Python?! Created in 1991, became increasingly popular – especially in university circles – only in the mid-2000s, and then completely exploded thanks to the ML/DL boom of the 2010s. That boom fed back into programming training, and it's now a very popular first language too.
Love it or hate it, Python was a teenager by the time it properly took off.
You can code your quines in whatever you'd like, but a serious project needs existence of good tooling, good libraries, proven track record & devs that speak the language.
There are serious projects being written in D as we speak, I'm sure, and the language has a track record of having been consistently maintained and improved since 2001, and has some very good libraries and tooling (very nice standard library, three independent and supported compiler implementations!) It does not have good libraries and tooling for all things; certainly integrations with other libs and systems often lag behind more popular languages, but no programming language is suitable for everything.
What I'm saying is there's a big world out there, not all programmers are burdened with having to care about CV-maxxing, community or the preferences of other devs, some of them can just do things in the language they prefer. And therefore, not everything benefits from being written in Rust or whatever the top #1 Most Popular! Trending! Best Choice for System Programming 2026! programming language of the week happens to be.
Zig has one implementation and constant breaking changes.
D is the far more pragmatic and safer choice for serious projects.
Not that Zig is a bad choice but to say that a unstable lang in active development like Zig would be a better choice for "serious projects" compared to a very well established but less popular lang shows the insanity of hype driven development.
You are totally right, sir.
>You can code your quines in whatever you'd like, but a serious project needs existence of good tooling, good libraries, proven track record & devs that speak the language.
Now, you HN user who calls yourself 4gotunameagain (which type of name is already a red flag for those in the know, because usually used by trolls), do us a favour by posting the link to at least one of your so-called serious projects here. Put your money where your mouth is.