That is the no longer the case in C# 14/.NET 10, D has lost 16 years counting from Andrei's book publishing date, letting other programing languages catch up to more relevant features.
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.
> Mixing C# with other languages in the same project is also difficult because it only supports MSBuild.
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.
> Rust also has issues using anything besides cargo.
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.
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.
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.
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.
I'm not saying D didn't have nice features - but if D/C#/Java are valid options I'm never picking D - language benefits cannot outweigh the ecosystem/support behind those two. Go picked a niche with backend plumbing and got Google backing to push it through.
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++ :)
> 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.
Its not the GC, its that D has no direction. Its kitchen sink of features and the optionality just fragments the ecosystem (betterC, gc) etc, making reusing code hard.
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.
go had a similar early trajectory where c++ programmers rejected it due to the gc. it gained traction among python/ruby/javascript programmers who appreciated the speed boost and being able to ship a single static binary.
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 ...
> You never get a second chance at making a good first impression.
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.
> The fact that C# is becoming the GC language in game dev is proving my point.
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
C# wouldn't be a problem for Unity if they hadn't mapped most engine abstractions to class hierarchies with reflection-based dispatch instead of value-type handles and the seldom interface, and had dropped the Boehm GC. .NET has actually got a lot of features to avoid allocations on the hot paths.
I agree Mono is bad compared to upstream .NET, but I used to write game prototypes with it back before .NET Core without as many performance issues as I still find in Unity. It was doable with a different mindset.
AFAIK, the original reason to build IL2CPP was to appease console certification and leave behind Mono's quirky AOT on iOS. Capcom is also using their own C# implementation targeting C++ for console certification.
Allegedly some games are now managing to ship on console with ports of .NET NativeAOT.
> The fact that C# is becoming the GC language in game dev is proving my point.
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.
dplug is a framework for building audio plugins that do realtime signal processing, and its creator has produced several well-sold plugins under the "Auburn Sounds" studio name.
Interesting. That might fit the bill, though I am not completely sure.
Do you happen to know why D has not been accepted into the benchmarks games at debian.net? I heard that D developers contributed D code, but that D was never accepted.
D by definition meets the FFmpeg's criteria because it's also a C compiler. Because of that I never wondered how D performs in the benchmarks, as I know for sure that it can give me the performance of C where I need it.
But then, to use D for performance, would I then have to master both D, C and their interaction? That doesn't seem great. It's like having to learn 2 languages and also how they interact.
No, you can just write D. It'll have the same performance as C, if you write C-like code. It might have better performance than C if you use templates (just like in C++).
Not necessarily, you can just call the functions in the C library from D as you'd call them from C or C++ with the added benefit of being able to leverage the D GC, RAII, macros etc.
Dunno about the Debian benchmarks game or their build environment. I did my own benchmarks and it was quite easy to write working D code compared to C, C++ or Rust. I used LDC, the LLVM D compliler as opposed to DMD. Dub is not that seamless compared to Cargo but given that you have to set things up manually, it doesn't encourage dependency hell.
If you're writing networking code, Go is probably a better choice than vibe.d.
You can use C but you are not forced to. In fact, you can write C and convert it automatically to D (though it will need some amount of manual editing afterwards). C is supported as a syntax option but it's still the same compiler for both under the hood. As rightly pointed out by the user above, you can write the same high performance code in the D syntax. The reverse is not true, though -- using high level concepts like classes and GC allocation is not supported in the C syntax.
I'd say D's template error messages are much better than C++'s, because D prints the instantiation stack with exact locations in the code and the whole message is just more concise. In C++, it just prints a bunch of gibberish, and you're basically left guessing.
To be a modern and sane C++ that C++ could have been, (rather than a complex collection of tacked on languages that C++ is), with modules instead of the the mess of C++'s headers, with instant compilation times that does not need a compilation server farm.
One good case for it that I see is a viable basis for cross-platform desktop apps. Today, cross-platform desktop GUI apps are either just a snapshot of the website contained inside Electron, or a C/C++ code base with manual memory management. D can serve as a nice middle ground in that space.
Where is the extensive tooling support for this use case if that is where you think it fits?
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.
It's true that there is no off the shelf tool that you can use right now to write your app, but it certainly doesn't prove that making such a tool is impossible or even complicated.
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.
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.
The term 'Cowboy coder' has been around for some time. Everybody's favourite unreliable source of knowledge has issues dating back to 2011: <https://en.wikipedia.org/wiki/Cowboy_coding>
On the flipside, with OOP is usually quite easy to put a debugger breakpoint on a particular line and see the full picture of what the program is doing.
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.
That is true, but on the flip-flip side, while procedural or FP programs are usually easy to run piecewise, with OOP, you have to run the entire app, and navigate to the statement in question to be even able to debug it.
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.
> 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!
This is not true. It took about 20 years for Python to reach the levels of its today's popularity. JavaScript also wasn't so dominant and omnipresent until the Chrome era.
Also, many languages that see a lot of hype initially lose most of their admirers in the long run, e.g. Scala.
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.