IMHO D just missed the mark with the GC in core. It was released in a time where a replacement for C++ was sorely needed, and it tried to position itself as that (obvious from the name).
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
I used to think of D as the same category as C# and Java, but I realized that it has two important differences. (I am much more experienced with Java/JVM than C#/.Net, so this may not all apply.)
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.
Native calls from C# are MUCH better than then the Java experience. It's a massive part of why I chose it when it came out. Today, C# is pretty great... not ever MS dev shop, which is often, like Java, excessively complex for its' own sake.
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.
I'd rather say that the GC is the superpower of the language. It allows you to quickly prototype without focusing too much on performance, but it also allows you to come back to the exact same piece of code and rewrite it using malloc at any time. C# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless.
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# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless.
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.
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.
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
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.
>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.
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.
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.
It's pretty obvious from the context that runtime/GC means having a runtime with a tracing GC - and the tradeoffs are well known. These discussions were played out over the last two decades - we all know GC can be fast, but there were and are plenty of use-cases where the tradeoffs are so bad that it's a non-starter.
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 :)
Zig got too much in to avoiding "hidden behavior" that destructors and operator overloading were banned. Operator overloading is indeed a mess, but destructors are too useful. The only compromise for destructors was adding the "defer" feature. (Was there ever a corresponding "error if you don't defer" feature?)
No, defer is always optional, which makes it highly error prone.
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.
Re: the point about Zig: Especially considering I used and played a lot with D's BetterC model when I was a student, I wonder as a language designer what Walter thinks about the development and rise in popularity of Zig. Of course, thinking "strategically" about a language's adoption comes off as Machiavellian in a crowd of tinkers/engineers, but I can't help but wonder.
FIl-C, the new memory-safe C/C++ compiler actually achieved that through introducing a GC, with that in mind I'd say D was kind of a misunderstood prodigy in retrospect.
There's two classes of programs - stuff written in C for historic reasons that could have been written in higher level language but rewrite is too expensive - fill c.
Stuff where you need low level - Rust/C++/Zig
I often see people lament the lack of popularity for D in comparison to Rust. I've always been curios about D as I like a lot of what Rust does, but never found the time to deep dive and would appreciate someone whetting my appetite.
Are there technical reasons that Rust took off and D didn't?
What are some advantages of D over Rust (and vice versa)?
> Are there technical reasons that Rust took off and D didn't?
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.
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.
D and Rust are on the opposite sides at dealing with memory safety. Rust ensures safety by constantly making you think about memory with its highly sophisticated compile-time checks. D, on the other hand, offers you to either employ a GC and forget about (almost) all memory-safety concerns or a block scoped opt-out with cowboy-style manual memory management.
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.
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
> Are there technical reasons that Rust took off and D didn't?
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.
One feature of D that i really wish other languages would adopt (not sure about Rust but i also think it lacks it, though if it has it to a similar extent as D it might be the reason i check it again more seriously) is the metaprogramming and compile-time code evaluation features it has (IIRC you can use most of the language during compile time as it runs in a bytecode VM), down to even having functions that generate source code which is then treated as part of the compilation process.
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).
Arguably, most of the metaprogramming in D is done with templates and it comes with all the flaws of templates in C++. The error messages are long and it's hard to decipher what exactly went wrong (static asserts help a lot for this, when they actually exist). IDE support is non-existent after a certain point because IDE can't reason about code that doesn't exist yet. And code gets less self-documenting because it's all Output(T,U) foo(T, U)(T t, U u) and even the official samples use auto everywhere because it's hard to get the actual output types.
Rust has procedural macros, which turn out to be a good-enough substitute for real compile-time reflection for surprisingly many use cases, though nowhere near all of them. (In particular, Serde, the universally-adopted framework/library for serializing and deserializing arbitrary data types, is a third-party library powered by procedural macros.)
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.
> 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.
D has much better metaprogramming compared to Rust. That has been one of the only things making me still write a few D programs. You can do compile time type introspection to generate types or functions from other elements without having to create a compiler plug-in parsing Rust and manipulating syntax trees.
Rust has some of the functional programming niceties like algebraic data types and that's something lacking in D.
More like the companies that jumped into D versus Rust, D only had Facebook and Remedy Games toy a bit with it.
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.
> Many of us believe on automatic memory management for systems programming
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.
Go wasn't around when D was released and Java has for the longest time been quite horrible (I first learnt it before diamond inference was a thing, but leaving that aside it's been overly verbose and awkward until relatively recently).
> (People who want that sort of stupidity already have Go and Java, they don't need D.)
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.
As far as adoption is concerned, I'm not sure it should be that big of a concern.
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.
GCC usually drops frontends if there are no maintainers around, it already happened to gcj, and I am waiting for the same to happen to gccgo any time now, as it has hardly gotten any updates since Go 1.18.
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.
I like D in general, however it is missing out in WASM where other languages like Rust, Zig, even Go are thriving. Official reasoning usually included waiting for GC support from WASM runtime, but other GC languages seem to just ship their own GC and move on.
OpenD added almost-full (you can't catch exceptions or spawn threads, so not really full, but the GC and such work fine) wasm support with like .... i think it was less than one day of work. wasm sucks though, what a miserable platform.
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.
When I was student, our group was forced to use D lang instead C++ for CS2* classes. That was back in 2009. After 16 years I see that level of adoption did not change at all.
You'd be surprised to see how active the D community is, despite your fair point that it's noticeably smaller than in the "competing" (in quotes because it's not a competition, actually) languages.
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.
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
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.
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.
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.
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.
Dead Comment
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
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?
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.
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.
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 :)
Look at C#'s competitive placings with C++/Rust on The Computer Benchmark game due to .NET's ruthless optimization.
Swift seems to require reference counting significantly more than Rust.
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.
Are there technical reasons that Rust took off and D didn't?
What are some advantages of D over Rust (and vice versa)?
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.
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.
And I am here, enjoying both. Life is good.
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.
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
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.
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).
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.
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.
Rust has some of the functional programming niceties like algebraic data types and that's something lacking in D.
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.
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.)
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.
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.
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.
Also, this presentation https://accu.org/conf-docs/PDFs_2007/Alexandrescu-Choose_You... killed a lot of bike shedding!
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.
1. https://dlang.org/changelog/2.112.0.html
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