Each of those paradigms has its place, and I enjoy being able to mix and match them as appropriate in the same program.
You're not forced to use the features you don't need.
There are some pain points that could probably go but realistically the aim is to make writing efficient code easy and abstract code even easier within the same language.
If you learn D you get to avoid a bunch of legalese compared to C++, and lots of runtime bugs compared to Python - there are more features to learn, but they generally make quite a lot of sense when you need them e.g. Ada-style contract programming is extremely useful the moment you don't have it.
I always had the sense - without seriously looking into it though - that D was about avoiding some of the mistakes/mis-features of C++, but C++ is always getting new stuff, which doesn't sit exactly well with what D has chosen, and then it plays somewhat clunky catch-up. But I may be very wrong.
My opinion is that D lost its goal on the way. It was indeed supposed to be a cleaner C++ without all its confusing history of layers of features over layer of features. And it was so, for sometime. But then they started adding this, and this, and that, everything and all sorts of kitchen sinks depending on the fad of the year; meta-programming, taking from C++, or lately rustifying itself. The current state looks to me is as indigestible as modern C++ (and the process to get there has largely been the same, the process the original goal of D meant to rid and avoid). A pile of templates and annotations. D's evolution has been a great disappointment to me. I can see Nim going that way too.
CTFE in D works as you would expect, constexpr is a weird hack.
Concepts in C++ are ridiculously overcomplicated and are done with a much simpler solution in D.
Ranges are also much better thought out in D.
C++ will also never replicate D's ease of use when it comes to metaprogramming - static foreach and if for example have no alternative in C++ (if constexpr is incredibly stupid)
Sink your teeth into that. Code generation at compile time, functional programming etc.
The compiler can actually check that this is pure for you but in this case it isn't performed so it can read from stdin
Would you care to elaborate what's wrong with it? When I used it I always felt it was quite straightforward.
Constexpr tells you what you can do. It adds huge amounts of bulk to the standard, there is syntax soup everywhere now etc.
One thing C++ will never have is D's `static if`, which allows injecting declarations into scopes. Bjarne Stroustrup and others closed that door: https://isocpp.org/files/papers/n3613.pdf
don't be so sure
https://github.com/lock3/meta/wiki/Metaprogramming-Introduct...
a lot of it is already implemented: https://cppx.godbolt.org/z/4arx6T
See e.g. https://youtu.be/8c6BAQcYF_E
The following example is similar to C macros because it generates code as string and mixes it in as code but you can combine templates as well. This example generates a struct definition.
(Edit: formatting)
import std; // Entire package for brevity
auto memberDef(string type, string name) {
return format!" %s %s;"(type, name);
}
auto memberDefs(string[] members...) {
return (members
.chunks(2)
.map!(pair => memberDef(pair[0], pair[1])));
}
auto structDef(string name, string[] members...) {
return format!q{
struct %s {
%-(%s%)
}
}(name, memberDefs(members));
}
unittest {
mixin (structDef("Foo", "int", "i", "double", "d"));
auto f = Foo(42, 1.5);
assert((f.i == 42) && (f.d == 1.5));
}
void main() {
}For example C++20 has constexpr, consteval, constinit, for a less powerful equivalent of D's CTFE.
D use no syntax for this. Things are evaluated in CTFE when they can. The rules are simple, and you can ignore them for the first few years. It's because CTFE is considered a normal thing in D.