There's no mystery. It's a jack of all trades, master of none. E.g., the virality of the GC makes it a non-starter for its primary audience (C/C++ developers). The need to compile and the extra verbosity makes it a bad substitute for scripting like Python. Etc.
Basically, name any large niche you'd expect it to fill and you'll probably find there's a tool already better suited for that niche.
No. If you were to say you need the GC to use all features of the language and standard library, of course, the GC does important things, but to claim a C developer wouldn't be comfortable with it because of the GC is nonsense. Just don't allocate with the GC and use the same mechanisms you'd use with C (and then build on top of them with things like @safe, reference counting, and unique pointers).
> Just don't allocate with the GC
"virality" is not just a word you can ignore.
What you're suggesting is the moral equivalent of "it's easy to avoid diseases, just avoid contact with those infected", or "it's easy to avoid allergens, just avoid foods you're allergic to", or "it's easy to avoid contamination, just set up a cleanroom", or "it's easy to write deterministic code, just avoid randomness", etc.
Yes, there are things that are easy to achieve in the vacuum of outer space, but that's not where most people are interested in living.
Thank you. Yes, exactly. The problems aren't even subtle; it's impossible to miss them if you actually try. I don't recall even finding a reasonable way to concatenate or split strings on the heap and return them without a GC, let alone anything more complicated. It boggles my mind that people repeat the talking point that it's somehow practical to program with @nogc when the most basic operations are so painful. Nobody is going to drool at the idea of spending days/weeks of their lives reinventing nonstandard second-class-citizen counterparts to basic types like strings just to use a new language.
> They want to make the situation better but there’s just not enough people to tackle the huge amount of work that requires (I.e. changing most of the stdlib)
I don't agree that it's lack of manpower that's the problem -- at least, not yet. I think it's primarily the unwillingness to even admit this is a problem (an existential problem for the language, I think) and confront it instead of denying the reality, and secondarily the inertia and ecosystem around the existing language outside the standard library. It's not like the problem is subtle (like you said, a few minutes of coding makes it painfully obvious) or novel. The language has been out there for over a decade and a half, and people have been asking for no-GC version nearly that long. Yet, at least to the extent I've had the energy to follow it, the response has always been the canned you-can-totally-program-D-without-a-GC denials you see repeated for the millionth time here, or (at best) silence. If this sentiment has changed and I'm unaware of it, that's already significant progress.
Maybe the unwillingness to confront reality is due to the lack of manpower and how daunting the problem looks; I'm not sure. But it seems as bright as daylight that D is not going to be successful without solving this problem.
https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ba...
It's pretty minimalist on purpose. I don't much care for kitchen sink types.
The BetterC is the no-gc version. Use the -betterC switch on the compiler.
Or, if you want a string result,
import core.stdc.stdlib;
string concat(string s1, string s2)
{
const length = s1.length + s2.length;
char* p = cast(char*)malloc(length);
assert(p);
p[0 .. s1.length] = s1;
p[s1.length .. s1.length + s2.length] = s2;
return cast(string)p[0 .. length];
}
I tend to not use this sort of function because it doesn't manage its own memory. I use barray instead because it manages its memory using RAII. D provides enormous flexibility in managing memory. Or, you can just leave it to the gc to do it for you.I feel you're demonstrating exactly the problems I highlighted through your example here -- including the very lack of acknowledgment of the overall problem.
The very simplest and straightforward way is to use the gc to manage the memory. It works very very well. All the other schemes have serious compromises.
That's why you can use the method most appropriate in D for the particular usage. I routinely use several different methods.
And funny, C++ has been copying many features that DLang have for many time ago. Beginning with the type inference (ie using "auto" to declare vars). And now, contractual programing and static reflection.
I really loved the language, but it's very sad that never manages to take off and become more popular and well maintained.
And while some features in other languages might have seen an implementation first in D, claiming first to the finish line as it usually comes up, even on this thread, hardly does anything for language adoption.
On the contrary, it is one reason less leave those languages, as eventually they get the features, and already have the ecosystem.
Most of the stuff that interested me back in 2007, is now available across in C#, F#, JVM languages, Swift, OCaml, Haskell, with a better ecosystem and IDE tooling.
And then there is C++26 and Rust 2024.
You achieved a lot as language designer, but it is still not clear how the community would keep the language going forward in lets say 10 years from now.
GCC (and possibly other compilers) had typeof in the '90s well before D was first released. Macros in the form:
#define TYPEOF(name, expr) typeof(expr) name = expr
Were widely in use since then.I'm sure that C++ borrowed concepts from D, but type deduction (not inference BTW) is not one of them.
It's a prototype to gauge the interest in having a borrow checker in the language. I did not continue with it because the interest is not there.
I've been happily using D for a better experience with C code for more than a decade. First, because it's extremely rare to need to completely avoid the GC for everything in your program. Second, because everything you want and need from C is available, but you can use it from a more convenient language. Sure, exceptions won't work if you're avoiding the GC (which doesn't have anything to do with C), but so what. It's not like C programmers are currently using exceptions. You can continue to use whatever mechanism you're using now.
that works if your main use case for d is as a top-level wrapper program that is basically calling a bunch of c libraries. if you want to use d libraries you will run into ones that need the gc pretty quickly.
I don't think what hinders their adoption is their direction, everything they say they accomplished/plan to accomplish is ideal IMO.
Having strictly more features (if we even assume that, which I don't think is accurate) does not imply better.
Javascript is just JSON with more features too. Is it a mystery that people don't ship Javascript code everywhere instead of JSON?
Another example is D enables nested functions. Yes, there are ways in C to do the equivalent, but they are clumsy and indirect.
D does escape analysis from an alternative direction. If a pointer is qualified with `scope`, the compiler guarantees it does not escape the stack frame.
(D's ability to use C code is to make use of existing C code. There's not much point to writing C code to use with D.)
That's kind of why I said it's the "jack of all trades". It's not a bad language, it just doesn't beat any existing languages I know of in their own niches (hence "master of none"), so few people are going to find it useful to drop any existing languages and use D in lieu of them.
D also attracts expert programmers who are very comfortable using the GC when appropriate, stack allocation when appropriate, malloc/free, even ref counting. These are just tools in the toolbox, like I use socket wrenches, end wrenches, box wrenches, crow foot wrenches, pipe wrenches, monkey wrenches, etc. I don't try to use socket wrenches for everything.
BTW, the GC makes managing memory in compile time function execution trivial. Something that non-GC languages struggle with.
I guess what I've been trying to say is that you would find yourself pleased much, much more often (and D being much more successful) if you recognized and addressed these high-level issues that people have been pointing out for decades, instead of denying them and going on forums telling customers why their expectations are wrong or unnecessary. I'm saying this because D really is a great piece of technology that got a lot of things right, except a few crucial details for some of the most crucial users. And it has had so much potential - potential that has been gradually lost largely because you haven't even recognized the flaws and hurdles that come with it.
It remind me of the infamous Dropbox comment. It's as if you invented FTP, but then whenever people told you it's hard to store & share files, you kept insisting that it's trivial with just a few simple steps on Linux, completely missing the massive market opportunity and the barriers you're telling people to walk through. https://news.ycombinator.com/item?id=9224
And I'm not saying all this out of out hate for D, but out of (at least past) love for it. I desperately wanted to see it succeed, but I gave up because I realized you simply did not see the Achilles heel that frustrates many of its users and that has held back its potential.
Not only is this assuming bad faith (against the rules, and kind of insulting) but it's just manifestly false.
Nobody was expecting or complaining about lack of foresight, denying the hard work that went into the language, or blaming anyone for not being perfect. D had a fantastic vision ahead of its time, with a ton of blood, sweat, and tears poured into it, and a ton of people wanted to see it dominate, including me. Yet... it did not, and its lunch (becoming the successor to C or C++ for a large portion of their users) is now being slowly eaten by other languages, most notably Rust.
You hopefully saw [1] that I was not the only one being frustrated with the virality of the GC. It took until DMD 2.066 (2014, some 7 years after D 2.0's release, with years of people complaining repeatedly in the interim -- just a year after Rust's initial release) for enough of the GC's problems to be acknowledged that @nogc was finally introduce to make it even possible to detect the lack of GC in a program. 11 years later, we still aren't even seeing an acknowledgment of the other long-standing, well-known problems I (and others) have gone through great pains to re-outline above -- let alone even a statement that anyone has any intention to even attempt addressing them.
Summarizing all of this as "virtue signaling" and "blaming people for not being perfect or having perfect foresight" when many of us users who have otherwise loved the language were incredibly frustrated with these GC problems and hoping for at least a mere acknowledgement at some point over the past 18 years of hindsight makes for an incredibly gross characterization of both the reality we've faced and everyone's goals here.
"if you recognized and addressed these high-level issues that people have been pointing out for decades, instead of denying them and going on forums telling customers why their expectations are wrong or unnecessary"
There is a great irony that a replacement to C++ should have lots of features in it. (Not necessarily the same too-many features.) One of the key requirements of a real C++ alternative would be fewer language features.
Because at the scale many companies use C++, the additions into ISO C++, for how bad WG21 process currently might be, don't land there because a group of academics found a cool feature, rather some company or individual has seen it as a must have feature for their industry.
Sadly also a similar reason on how you end up with extension spaghetti on Khronos APIs, CSS levels or what have you.
Naturally any wannabe C++ replacement to be taken seriously by such industries, has to offer similar flexibility in featuritis.
Maybe it's just me but, sorry, I cannot parse this sentence.
As bad as the WG21 process might be, the additions into ISO C++ don't land there because a group of academics found a cool feature; they land there because some company or individual has seen it as a must-have feature for their industry.
You 100% cannot do that. I mean, you can if you're writing some toy project just for your own use. But as soon as you start interacting with other programmers, it's inevitable that some will use some other subset of language features.
> Can you briefly explain which features can be thrown out and language will not miss a lot without them?
I don't think that it's controversial that C++ is a huge language with many features, and I doubt I'm the best person to rehash that. One often quoted example is the multitude of ways to initialise a variable (Foo x = y; Foo x(y); Foo x = {y}; Foo x{y} and for default initialisation Foo x; Foo x = {}; Foo x{}; Foo x() (not really - that's the most vexing parse); Foo x = Foo()). There's multiple syntaxes to define a function including auto and decltype(auto) return types. There are const, consteval and constexpr - you may know the difference but I've forgotten. There are so many templating features that I wouldn't know where to start. Concepts are layered on top of that - which are useful and a good idea but no denying that it's layering extra complexity on top (which can be said for many C++ features). I've really just scratched the surface.
The thing is, I learned C++ over 20 years ago, when the latest standard was C++03 (which was essentially the same as C++98). Even at the time, C++ seemed like a bit of a chunky language (e.g., compared to C or Object Pascal - languages tended to be simpler back then), but it was achievable to mostly understand it all. But each revision that passed has added a huge volume of features. So I really feel how big C++ is because it's even big compared to (an older version of) itself. I've mostly kept up over the years but I can't imagine how I would properly learn the language today from scratch - I feel like you don't really stand a chance unless you've also been closely following it for decades.
I disagree. Such a problem will be in any language. So, any project should have a code style which will describe how you can do things and how you should not do them.
> I feel like you don't really stand a chance unless you've also been closely following it for decades.
From my experience, 2 years is enough. I started from zero and now I'm pretty good in C++. Although this can look like a really long time, but you should consider that to understand a lot of parts of C++ you need knowledge in computer science and programs design, which you should learn with any other language too.
Re: your first sentence: I neither understand the logic nor do I understand how insulting the developer is going to help D succeed here even if the logic was sound.
That's not data science or AI; "more famous" -- ridiculous distinction.
Fun fact: Ansible is orchestrated Python. Half your Linux distribution of choice is a pile of Python scripts. It's everywhere.
BTW:
I am not fond of stuff like:
// Sort lines
import std.stdio;
import std.array;
import std.algorithm;
void main()
{
stdin
.byLine(KeepTerminator.yes)
.uniq
.map!(a => a.idup)
.array
.sort
.copy(stdout.lockingTextWriter());
Are there any ways to do this that do not involve a bunch of "."s? I do not understand "map!" and "a.idup" either, FWIW.I really want to like D, but it tries to do too many things all at once, in my opinion.
Perhaps I will give C3 a fair try.
`map` is an operation on a data structure that replaces one element with another, in this case `a` gets replaces with `idup(a)`. The `idup` makes a copy of its argument in memory, and marks the data is immutable.
How would it look like with this particular code? Just for comparison.
> The `idup` makes a copy of its argument in memory, and marks the data is immutable.
How is one supposed to know this? Reading the documentation? I really want to look at the code and be able to know straight away what it does, or have a rough idea.
As for idup... The first several search results for "dlang idup" are all useful.
> I really want to look at the code and be able to know straight away what it does, or have a rough idea.
I presume you really don't like perl, ML based (ocaml, f sharp, rust) Haskell or K.
[1] https://news.ycombinator.com/item?id=44359539
> As for idup... The first several search results for "dlang idup" are all useful.
Yes, I am sure it was, I am sure an LLM would have helped too, but I think that is besides the point here.
$string =~ s/\d+/NUM/g;
I don't have a clue what is going on. Sure, I see the regex, but what is =~ doing?
There's only so far you can stretch most languages before you need to actually put in effort to learn them.
FWIW, I knew this as a kid, too, despite knowing absolutely nothing about the language at the time.
Anyways, you should read https://news.ycombinator.com/item?id=44463391 if you care about why I dislike the way D does it.
> How would it look like with this particular code? Just for comparison.
I do not know how to write D, so the following might not compile, but it's not hard to give it a go:
copy(sort(array(map!(uniq(byLine(stdin, KeepTerminator.yes)), a => idup(a)))), stdout.lockingTextWriter())
> > The `idup` makes a copy of its argument in memory, and marks the data is immutable.> How is one supposed to know this? Reading the documentation? I really want to look at the code and be able to know straight away what it does, or have a rough idea.
Are you serious? You are offended by the idea of reading documentation?This is not helping the credibility of your argument. Again, I'm not a D user, but this is just silly.
If you knew me, and you read my comment history, you would have NEVER said that. It is not even a matter of reading the documentation or not. "idup" seems arbitrary, sorry, I meant the whole line sounds arbitrary. Why "a"? Why "a.idup"? Why "map!"? I was asking genuine questions. You do not have to bash me and see ghosts. I was curious as to why it was implemented the way it was.
I am an active speaker against people who hate reading the documentation.
And FYI, I love Perl[1] and OCaml[2].
[1] https://news.ycombinator.com/item?id=44359539
[2] You would have to check the comment history.
a<b<arg>>
and now a means greater becomes a shift right.
That's one of the reason that it you had a genious ideo to find domething else in Da(template params)(runtime params) at declaration a!(template params)(runtime params) at invocation with the type deduction and parenthesis omission making often even disappear completely the template syntax.
thank you
`a` is a parameter in the lambda function `a => a.idup`.
> Why "map!"
This is definitely something that can trip up new users or casual users. D does not use <> for template/generic instantiation, we use !. So `map!(a => a.idup)` means, instantiate the map template with this lambda.
What map is doing is transforming each element of a range into something else using a transformation function (this should be familiar I think?)
FWIW, I've been using D for nearly 20 years, and the template instantiation syntax is one of those things that is so much better, but you have to experience it to understand.
> "idup" seems arbitrary
Yes, but a lot of things are arbitrary in any language.
This name is a product of legacy. The original D incarnation (called D1) did not have immutable data as a language feature. To duplicate an array, you used the property `dup`, which I think is pretty well understood.
So when D2 came along, and you might want to duplicate an array into an immutable array, we got `idup`.
Yes, you have to read some documentation, not everything can be immediately obvious. There are a lot of obvious parts of D, and I think the learning curve is low.
> Yes, but a lot of things are arbitrary in any language.
I disagree, but to each their own.
> Yes, you have to read some documentation, not everything can be immediately obvious.
I do not disagree, but I wanted to know the rationale behind it ("map!(a => a.idup)")!
How is one supposed to know this?
> How is one supposed to know this? Reading[…]?
Yes?
> I really want to look at the code and be able to know straight away what it does, or have a rough idea.
You said elsewhere that you love Perl. Would you say your sentence above applies to Perl?
Funny though, because most of the things these people accuse me of are dead wrong, and my comment history is proof of that. In fact, I have been down-voted to oblivion for telling people to read the documentation. I guess we may have come full circle.
Glad we had this utterly pointless chat.
Then again, it is entirely subjective, and we should not argue about taste.
To each their own.
* https://learn.microsoft.com/en-gb/dotnet/api/system.linq.enu...
* https://learn.microsoft.com/en-gb/dotnet/api/system.linq.enu...
stdin
.byLine(KeepTerminator.yes)
.uniq
.map!(a => a.idup)
.array
.sort
.copy(stdout.lockingTextWriter());
I would like to emphasize that this is a personal preference. No need to continue to bash me over it.I prefer Elixir's |> operator, if you want an example of something I prefer.
print join '',
sort { $a cmp $b }
grep { !$seen{$_}++ } # = uniq
<STDIN>; stdin
|> byLine(yes)
|> uniq
|> map(a => aidup)
|> array
|> sort
|> copy(stdout)
I’m sorry if you took it as bashing. It’s mere curiosity as I’ve never seen that preference before."map(a => aidup)" caught me by surprise, too. Would Elixir do such a thing?
IO.stream(:stdio, :line)
|> Stream.map(&String.trim_trailing/1)
|> Enum.uniq()
|> Enum.map(&String.duplicate(&1, 1))
|> Enum.sort()
|> Enum.each(&IO.puts/1)
This is not equivalent in style or presentation to: stdin
.byLine(KeepTerminator.yes)
.uniq
.map!(a => a.idup)
.array
.sort
.copy(stdout.lockingTextWriter());
Personally, I find the D version visually unappealing (and confusing), especially the way "stdin" sits alone on its own line, followed by a sequence of indented method calls. The excessive use of dots combined with the indentation structure makes it look, to me, rather awkward.That is just my own opinion.
People are too quick to use the "down-vote" button, and are too quick to judge. I love documentation, I write them. I am an active speaker against people who hate reading the documentation. This was not a case against reading documentation, yet people - wrongfully - believed so. People always glance past things like: "not fond of", and "in my opinion". It is tiresome.
This thread could have been educational, but instead it was a thread meant to bash me. It is my fault.
Go spread the way it did because it was dead simple to make websites and services, the syntax is insanely simple, but the language allows you to scale without going through a ton of hoops. Look at how much of our IT infrastructure is powered by Go now.
D has a lot of potential, but someone has to sit down and build frameworks and tooling for D.
I think if D had officially supported libraries by core maintainers that take full advantage of the best of D it might be a different landscape.
Another area where D could shine is GUIs. Everything is electron these days, it feels like nobody builds usable GUI stacks. If D had an official solution to this, and it worked nicely and gave you enough power to customize your UI, we might see a shift there too. I welcome a Electron free future.
Look at the Zed editor (ignore the AI buzz) and how insanely fast it is. Its coded in Rust, and uses WGPU iirc to just render everything kind of like a video game, but it runs insanely fast. It is my new favorite text editor.
Sadly despite my deep love of D, Go is where I'm leaning more towards, due to industry pull there.
I've often thought that, to the extent that I spent a while looking for some active projects I could contribute to, and came up blank. if I do have some new gui based program of my own I want to write I will at least consider d for it, though ocaml is another great language in the same space and I already have some experience with ocaml/gtk. my hope was that d would have more mature gui toolkit bindings and more of a community of people writing apps, which would have been some incentive to switch over from ocaml, I was disappointed to find that wasn't the case.
For some reason, and mostly that being Mozilla, Rust got quite an initial kick to overcome that initial hurdle in haste. We're not going to mention a lot of those libs are stale in Rust world, but at least they're there and that kind of gives you momentum to go forward. Whatever you're trying to do, there's a non-zero chance there's a library or something out there for you in Rust.. and we got there real quick which then encouraged people to proceed.
That's just like my opinion, man.. but I think a key part is that first lib bindings hurdle which Rust somehow went over real quick for a critical mass of it; D hasn't.
Love the D though lol, and Walter is a 10000x programmer if you ever saw one but it might be time to hang the hat. I can only imagine how a community like Rust or I don't know Zig of those up-and-coming would benefit from his help and insights. He'd probably single-handedly make rust compile 100x faster. One can hope.
That is basically table stakes for a new language now.
I know its petty - I still can't get past how idiotic and frustrating it is that Zig treats unused variables as a compiler error. Its the worst of all worlds:
- Its inconvenient (I have to explicitly suppress them in my code with _ = foo)
- Once I've suppressed them, I don't get any compiler warnings any more - so ironically, it takes more effort to find and fix them before committing. I end up accidentally committing code with unused variables more than in Rust or C.
- And it totally breaks my flow. I like to explore with my hands and run my code as I go. I clean up my code after my tests pass so I can be sure I don't introduce new bugs while refactoring.
Zig's handling of unused variables seems like an unforgivably bad design choice to me. Its been raised by the community plenty of times. Why hasn't it been fixed? I can understand if Andrew Kelly doesn't program the same way I do. We all have our idiosyncrasies. But does he seriously not have any smart people around him who he trusts who can talk him out of this design?
It seems like a huge pity to me. It otherwise seems like a lovely language.
Because yours is just an opinion. It's perfectly legitimate to not like unused variable errors, but its factually wrong to say that no one wants it. You're just yucking somebody else's yum.
> But does he seriously not have any smart people around him who he trusts who can talk him out of this design?
He does, most of them also like unused variable errors. For what it's worth, I do too.
The more time I spend thinking about it, the more convinced I am that its strictly worse. What am I missing? Why do you like it?
However, I've written a decent amount of Zig code and that's probably my biggest complaint. Zig has put a ton of effort into making an ultra-fast developer experience with very low iteration times, and it's amazing. But then when I'm refactoring some code or trying to figure stuff out by, for example, commenting out some lines of code, I might get a bunch of unused variable errors. And so I spend more time fixing those than I do even compiling the code itself!
One thing I've seen suggested is using the linter to automatically insert `_ = foo` for unused variables, but I don't love that either because then what even is the point of the error in the first place?
But like I said that's all downstream of the no-warnings policy. And I totally understand the failure mode of warnings - I've worked on plenty of large projects that had 4,000 warnings and everyone ignored them and the actually useful ones would be invisible. Is there some middle ground where, I don't know, Debug builds can have warnings, but Release builds don't?
Zig is a language that demands a lot of rigour of the programmer. It offers a lot of trust. Far more so than Go or even Rust. It’s in light of that philosophy that it seems so weird. The compiler trusts me to manually manage my memory, but it’ll scold me like a naughty child if I ignore an unused variable for 5 minutes? Pick a lane.
I’d love to hear some arguments in support of this choice. The closest I’ve heard is “it doesn’t bother me, personally” - which isn’t a very strong argument.
I’m a little tempted to fork the compiler just to fix this. Can’t be that hard, right?
For me any alternative to Rust implies having automatic resource managment, eventually coupled with improved type system, in a mix of affine types, linear types, effects or dependent types.
Something that in regards to safety is already available today by using GCC's Modula-2 frontend, FreePascal and similar, is not bringing too much to the table, comptime notwithstanding.
Automatic constructors - You only have to write the 'make me a box of two apples' code and not 'this is how two apples go into a box'! This is as revolutionary as 'automatic function calls', where you don't have to manually push the instruction pointer to pop it back off later.
Parenthesis omission!
If I were to parody this I'd talk about how good Scala is - in addition to classes, you can also declare objects, saving you the effort of typing out the static keyword on each member.
Sell me something nice! Millions of threads on a node. Structured concurrency. Hygienic macros. Homoiconicity. Higher-kinded types. Decent type inference. Pure functions. Transactions.
https://dlang.org/spec/function.html#pure-functions
D's pure functions are quite strict. It can be a challenge to write a function that passes strict purity guarantees - but the result is worth it!
int x = f(); // f() is run at run time
enum y = f(); // f() is run at compile timePlus the chicken and the egg problem. This is mostly from the AerynOS experience : it seems like if you want to write some moderately complicated code then you're becoming the upstream of many libraries. Especially now with Rust's popularity and ecosystem maturity on the rise, it's super hard to convince people (e.g. your boss) that you'd be better of with D compared to e.g. Rust.
I did not like DUB at all. Its default behavior was to not segregate artifacts by configuration, and trying to change that was a headache.
It’s too bad, though. It’s a nice language, but I can’t see it making any inroads at this point.
Then came the D2 re-write which broke backwards compatibility and took another few years.
In the meantime everyone moved on
No such thing happened. D has always been built on the same codebase, and the labels "D1" and "D2" are just arbitrary points on a mostly linear evolution (in fact, the tags D 1.0 and D 2.0 came only 6 months apart; 1.0 was just meant to be a long term support branch, not a different language. It was the addition of `const` that broke most code around release 2.6 but if you update those, old and new compilers generally work.
I'd say where D failed was its insistence on chasing every half-baked trend that someone comments on Hacker News. Seriously, look at this very thread, Walter is replying to thing after thing saying "D has this too!!" nevermind if it actually is valuable irl or not.
I am not sure if what supporting every paradigm is a definitely good thing though I feel like I would love the freedom to do so. I am a tinkerer at heart/first and a coder at second and my favourite language is probably go and then nim/julia/elixir/typescript/<it depends on the project>