On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
> ...
How any combination of UFCS, dynamic code generation and introspection, shortened syntax for calling functions, the ability to pass lambdas to templates (which can also be completely inlined by the compiler without sacrificing on code readability), etc can all be used to create and model code almost exactly how you want it to.
I very rarely feel constricted in D like I do in other languages. There's pros and cons to that of course, but when I feel like just tapping out something random, more often than not I can match the code model to my mental model.
e.g. the very existence of UDAs can allow for pretty natural looking code:
@Command("command", "This is a command that is totally super complicated.")
struct ComplexCommand
{
@CommandArgGroup("Debug", "Arguments related to debugging.")
{
@CommandNamedArg("verbose|v", "Enables verbose logging.")
Nullable!bool verbose;
@CommandNamedArg("log|l", "Specifies a log file to direct output to.")
Nullable!string log;
}
}
The above is doable in C#, but has to be done at runtime (assume the same with JVM languages).
However in C++ you probably have to do weird hacks or use an external tool. C is either the same as C++ or even worse.
Another example would be ranges, which we all know about (taken from D's main page):
import std.stdio, std.array, std.algorithm;
void main()
{
stdin
.byLineCopy
.array
.sort!((a, b) => a > b) // descending order
.each!writeln;
}
Or maybe I want to design a UI system where, with a small bit of descriptive boiler plate, I can automatically enable new controls to be used within a UI definition file:
@DataBinding
struct MyControlBinding
{
@BindingFor("stringVal")
string someString;
@BindingFor("intVal")
@Name("number")
int someInt;
}
@UsesBinding!MyControlBinding
class MyControl : UIBase
{
public string stringVal;
public int intVal;
}
UI:view {
name "Some sexy custom UI"
MyControl {
someString "Hey"
number 69
}
}
Or literally even just simple things like custom error messages:
struct Vector(size_t dims)
{
static assert(dims <= 4, "The dimension is too large!")
}
Then there's things like pegged, vibe-d's diet templates, etc... All of this is possible within a single language, using standard tooling.
Once I learned about how to introspect code and to generate code, the amount of possibilities really opened up to me.
D's expressiveness and modeling power is probably the biggest thing I'd say it has over most over languages. I feel even dynamic languages fail to do some of these things as elegantly.