It's a good article. The title is slightly bait-ey in that 'less fun' is a good thing in this context. C++ metaprogramming, at least for this example, requires a bunch of boilerplate. The D equivalent is built with standard language features and produces understandable error messages when mistakes are made.
It's a nice little anecdote about why you might want to use D in place of C++.
Java and C# are statically typed, garbage collected languages with a huge adoption and massive amounts of tooling.
D's attempt to become an alternative to C and C++ was eclipsed by Rust, which doesn't have the GC overhead and has a ton of other really compelling features.
There are a bunch of other new and exciting languages too: Go, Nim, ...
Why would anyone choose D today? (Serious question.)
> D's attempt to become an alternative to C and C++ was eclipsed by Rust, which doesn't have the GC overhead and has a ton of other really compelling features.
Rust isn't just a better C++, it imposes a new paradigm over resource management (lifetime oriented programming?). If you're coming from C++, you have to change your way of thinking.
D doesn't try to make you follow any paradigm (for the better and for the worse) ; and its syntax will feel natural and terse for a C++ programmer.
My experience (10 people team) has shown all C++ programmers can learn D very quickly. Is this the case for Rust?
> Why would anyone choose D today? (Serious question.)
Native speed, on-demand deterministic destruction, on-demand memory safety, metaprogramming, fast compile times, terse syntax.
I'm tempted to think that Rust doesn't really impose a new paradigm over resource management so much as it standardizes and enforces the common conventions of C++ resource management.
A major pain point probably is that people never really followed the "conventions" of C++ resource management as rigidly as Rust enforces them.
> A major pain point probably is that people never really followed the "conventions" of C++ resource management as rigidly as Rust enforces them.
That's exactly right. Rust does a great job moving idiomatic C++ best practices into the type system and actually forcing you to do it "right". And alot of the early pain people run into when switching to Rust is learning how to do this. I suspect very experienced C++ programmers have alot less challenge getting spun up on Rust. It's sorta front-loading the pain of discovering and learning C++'s best practices.
As a side effect, though, it means alot of Rust evangelism misses the mark as it mostly reveals their own C++ weaknesses (this is, on a different level, an indictment of C++, and its learning curve, but not really in the ways the evangelists often believe).
Productivity.
D is a very pragmatic systems language. C++ interop is basically unparalleled, UFCS makes writing libraries less traumatic and CTFE is just plain useful. On top of this, the type system is both concurrency aware and has the best generics I've ever used (Subjective as it gets, but that's my experience). If you want safety guarantees just tag a scope as @safe. Also, static reflection works really well.
Compiles(with DMD, ldc and gdc are still fast but are not as fast) are fast and
D is not really comparable with Go (For example). D is much more complex (and I my opinion simpler to write through said complexity, but obviously opinions differ), whereas Go is supposed to be simple to learn and implement.
> Really? So like your abstract goes in the main function, or how does that work? Do you use reference types for citations or just external symbols?
D has a documentation generator (Ddoc) as part of the language. It turned out to be useful as a standalone documentation generator. The dlang.org website is built using Ddoc, and I've even published a couple books in Ddoc. It feels a bit weird running a compiler over your marked up text, but that feeling passes after a while :-)
can D be used as drop in replacement for c++ in something like metatrader
i think, it might be worth it if you guy investigate areas like these, many trading platforms have interfaced to c/c++ if D and be added as a drop in replacement, with some more safety guarantees, you have a big niche market here that D can survive on for a long time
D interfaces very well with C/C++ code and libraries. It was designed to do that from the begining. Some D libs are actually bindings to C/C++ libraries. You don't need to replace existing C++ code/libraries, you can just integrate them in a D project.
It was in a rough time for Nim, around the transition from the old name, when the documentation was still being rewritten, and metaprogramming was a
magic few knew or used.
D and it's errors were just easier.
Not to say Nim isn't on my radar for new things, it just didn't quite fit at the time. (However, my first prototype was in Nim!)
but this is really a poor argument for D
your thesis code, isn't necessarily code that will be used by many people or shared with many developer (you didnt even share a link to the source code)
a thesis, just produce a proof of concept
D is unpopular , and I really believe that going after c++ was a bad idea .. if this was not clear at first, it should be clear by now, yet almost 100% of the article i see on D never stop from claiming how much better it is compare to c++
I guess the lesson learned from D's unpopularity is, when creating something dont focus on one competing tool
I recall how one time Linus Torvald, bashed subversion on how "Its goal is to be a mostly compatible successor to the widely used Concurrent Versions System" -- Wikipedia
Was a horrible design choice from the start
By focusing on C++ they added a GC, as an advantage (because C++ didnt have a GC)
but now that many people priase Rust for not having a GC and arguing they prefer C++ over D for it ... now they are trying to dis-integrate the GC ... very reactive, design decision ... and i doubt this will help much
> yet almost 100% of the article i see on D never stop from claiming how much better it is compare to c++
And I see the same from Rust and Go communities, hell I see it in Swift and Java communities a fair bit too.
That's not a real argument for or against a language. It just says the community will actually compare itself to other languages in similar fields. X vs Y articles are dime a dozen.
Some of Ds library inspired things in the new C standards, and D is influenced by other languages. I fail to see how that is a bad thing.
Common Lisp influenced Closure.
CoffeeScript influenced ES2005.
C has influenced Go.
Python, Nim.
That's just natural evolution. A language trying to become more flexible, is a good thing.
As someone who contends against the horrors of C++ daily, I wish the best of success for both Rust and D.
C++ is an incredibly popular collection of footguns and its replacement is a noble design goal.
Conversely, SVN is one of the tools which I use to archaeologize within a C++ codebase. It might not be right for the Linux kernel or other FOSS projects, but in the corporate world it works fine.
> Java and C# are statically typed, garbage collected languages with a huge adoption and massive amounts of tooling.
1. Java and C# are designed around JIT compilation, which results in a number of architectural choices that may or may not be to your liking.
2. The JVM and CLR are pretty heavyweight pieces of machinery.
3. Neither Java nor C# are particularly well-suited for working "close to the metal".
> D's attempt to become an alternative to C and C++ was eclipsed by Rust, which doesn't have the GC overhead and has a ton of other really compelling features.
This goes both ways: Rust doesn't have a GC, so if you want one, you're out of luck. For example, for most of what I'm doing – where GC works fine –, Rust offers me no benefit, but significant costs (note that this is a matter of application domains: the ones that Rust is designed for are simply not ones that matter much to me).
> There are a bunch of other new and exciting languages too: Go, Nim, ...
Go and Nim are indeed the languages that D is competing with more directly, but there's nothing wrong with having competition in this area, given that all of them are relatively new.
While I kind of like D, it's hard to really make the case for using it. The thing is, it simply doesn't provide that much of a significant advantage over modern C++14/17 to make it worthwhile. At least Rust introduces an entirely innovative new concept with the borrow checker. D is just basically C++ with optional garbage collection and better syntax for meta programming, but without the vast Universe of existing C++ libraries to leverage.
> D is just basically C++ with optional garbage collection and better syntax for meta programming, but without the vast Universe of existing C++ libraries to leverage.
Phobos, the D standard library, makes C++ standard library look very small.
C++14 standard library still can't do "ls", "execvp", "socket" in a portable way (but we finally got std::thread and std::function!).
Phobos can do all of this, and also haves support for md5, gzip, diff, sort, getopt, json, xml, ...
Thus the need for an external library is a lot less likely than it is in C or C++, and you almost never spend time rewrapping native stuff: it's already done by Phobos.
And in the end, if you need to use some specialized library, D can call C and C++ functions with zero overhead (I have D projects that use CGAL and SDL).
D also has nice opt-in reflection as an advantage over C++ (though there are C++ tools to make up for it, to an extent).
The reflection is IMO the killer individual feature (well, hand-in-hand with the codegen to actually use it). The rest is just the benefit of 1000 small things that all add up to a greater whole.
Yeah, automatic static reflection for serialization of standard-layout structs in C++ would certainly be nice. You can achieve something like that with std::tuple, but it's certainly not comparable to first-class serialization.
PS, I used to enjoy your posts on SDN, before the site owner threw a fit. :-)
In my line of work (real-time), C++ typically reigns supreme but D is just as fast and more productive, so why not use it?
It's not really about meta-programming, for me it wins on the basics.
I would like to use D if I could dump the GC, but it appears they don't make that easy, even though as you say it is possible. For me smart pointers make memory management seem not so daunting.
It's actually pretty easy. Just mark your code as @nogc, and it won't compile if there's anything that could potentially trigger a garbage collection. You obviously lose some functionality this way, but there's nothing difficult about avoiding the GC.
There are smart pointer libaries, and also implementing ref counting is much more straightforward than in C++ because the type system knows whether data is being shared or not.
I should add that the GC actually works perfectly fine for normal work, it justs not up to the competition (Partly because of having to work with traditional dynamic memory).
Since the article uses an event system as an example, I'm wondering: how well do closures work in D? (Closures are very convenient when dealing with events).
They work fine.
Everything is captured by reference, and is ultimately garbage collected.
Unlike C++, you're not required to use a special "local function" syntax.
> Is this all guaranteed to work also in a multithreaded environment?
Yes.
> How efficient is the garbage collector, and are there pauses?
Not very efficient, and there might be pauses if you are not careful.
Now if your closure doesn't escape (just a local function + context) it won't use the GC. So you can use delegates in @nogc code.
I'm a fan of Rust, but I think you must be reading a different HN if you don't think the Rust community focuses on comparing it to C and C++. The Go language creators have specifically stated that they created Go to solve problems they had with C and C++: http://web.stanford.edu/class/ee380/Abstracts/100428.html
C++ will always have a leg up over D for me due to the GC stuff. I like not having GC in C++.
When I want a GC'd C-like I use Go.
D has to find a space between those two for me and a lot of other people.
I don't dislike D. I think D has a LOT of great work done in it. I just really want all my libraries to be able to be used without GC. And I'm not sure it's really feasible to have each foot in either world and not just get split down the middle.
Can someone argue against this worry? It's literally the only thing stopping me spending more time with D.
Also I've been coding in Ada (lord help me) for fun. Contracts are interesting.
There's been a lot of work recently to enable GC-free D code. Yes, that means some of the standard library is off bounds, as are some of the built-in operators (new, array concatenation). However, you can have _static_ guarantees that there will be no GC allocations whatsoever. Writing an executable?
Remedy Entertainment has a talk - actually two talks, one from 2013 and one from 2016 [0], about how they added D to their game engine, replacing a major subsystem, and then shipped a AAA title(Quantum Break) with it. The GC did not present a major issue although the talk notes that their solution was "unfinished" and got the result they wanted by wasting memory instead of what they initially aimed for(ARC, this is work-in-progress for D [1][2]). Most of the nuts-and-bolts work came from achieving smooth integration with the C++ codebase, and building for the release devices.
I'm only lurking on the D forums, so this should probably be taken with a grain of salt. From what I understand the GC is required for various array, hash map and string operations, and things like closures and exceptions (maybe assertions?). Though there is work being done on fixes and alternatives (scope limitations, ref counted things).
This does seem to come up sometimes. I'm wondering if it makes sense to add a "end-vision for GC-less D" section to the D GC documentation, now that there are various undertakings to make it easier. Might also help with finding volunteers that care about @nogc to help out with various bits.
I've been told (in other threads on HN) that you can disable GC in D. I don't know how that integrates with stdlib (or other library) bits that use GC (are they disallowed, or do they fail at runtime?).
You can't allocate with GC in @nogc functions, you will get compile time error. There is ongoing work in standard library (Phobos) to make it work without GC.
After a while decreasing GC usage in D, I ended up removing it completely. I got reduced memory usage but no speed gain. What I've found is that before you remove the GC, you can turn the overhead from excessive to very affordable with optimizations.
Especially today with std.experimental.allocator and -profile=gc
> There is no guarantee that the GC won't run when calling GC.disable.
If you have called GC.disable, the collector becomes `return;`. Sure, the GC function is called, but it doesn't do anything, it just immediately returns.
I'm not sure tbh. The documentation says "Collections may continue to occur in instances where the implementation deems necessary for correct program behavior, such as during an out of memory condition." My understanding from the forum discussions is that a collection could happen and you would not know about it.
An important factor in choosing a language is platform. I'm not going to choose Go or D to write an iOS app in, because it would be painful and buggy, if it's even possible in the first place. I'm restricted to Objective-C(++) if I want it to really be a high quality & native app.
D can interface with Objective-C just fine. The Apple-provided tooling will indeed be more convenient for the developer, but the result the end user sees will be a "high quality & native app" just the same.
Most languages with a C FFI (and ARM/Mach-O compiler support) can do pretty well on iOS. Rust bindings to Objective-C APIs are pretty painless for example.
D... Doesn't have a large mindshare/corporation backing it.
I had a strong interest in D from 2007-2009. The problem is that there were two competing, incompatible standard libraries for D1 (Phobos and Tango). Then came D2, which was a large improvement, both language-wise and library-wise, but basically split the ecosystem in three for some time.
I think the library and D1 vs. D2 situation stifled the growth of D. I gave up on D because the community was so fragmented.
> dont reduce Rust and Go relative success to just having google or Mozilla
I don't think Go would have been popular without Google. It's easier to sell a solution to your manager when it is backed by a big org, and when people are paid fulltime to work on it. Same for Rust and Mozilla. The barrier for adoption of new languages is pretty high today in enterprise space.
Python became popular because many people saw it as a cleaned-up Perl, and ESR wrote about it.
Ruby became popular because of Rails.
Dart isn't popular because it was designed to be a browser language but did little to court Web developers who like JS (contrary to the HN consensus, a lot of Web developers actually like JS) or other browser vendors.
so you agree with me, we python and ruby didnt need a huge corporate backing and dart even with some corporate backing didnt become popular
more examples that debunk that corporate backing is what made rust or go ... are scala and clojure, scala being way more popular than d and clojure ... and neither have corporate backing
in conclusion, you dont really need corporate backing if you have a nicely designed language that have its own path
I found Rust by googling languages that compile to LLVM bytecode. It was version 0.6, but I was already excited by the fact that it was promising to be a fast, safe, concurrent language. Even back then it had a value proposition to early adopters.
I wrote a Fizzbuzz implementation. I did it to test language features. As language features and the standard library kept on changing, I kept updating my repository. It's had something like 70+ commits to it since 0.6 days.
These two comments are not mutually incompatible. There is also a reason I've been heard to say that Not Invented Here syndrome was invented at Bell Labs.
It's a nice little anecdote about why you might want to use D in place of C++.