Hacker News new | ask | show | jobs
by 10x-dev 1448 days ago
D is by far my favorite language. I put in a lot of effort to learn the language and thoroughly enjoyed discovering D's elegance. It has super clean solutions to all sorts of language issues (e.g. obj.foo() is just syntactic sugar for foo(obj), which gets you both type extensions and OO-looking methods on structs, which I miss in C).

That said I really tried to use D for my projects, but I had to give up for a rather surprising reason: the C interop is so good, that 1) most libraries provide a 1-1 translation of their C APIs, which ends up being ugly, non-idiomatic D that forces me to think in both C and D when coding; and 2) debuggers are not aware of D types and idioms, so when debugging, I have to again think in both C and D. Both of those add up to about 90% of the coding time, which is to say that, 90% of the time, when using D, I felt I had to code in 2 languages at the same time.

I'll skip some of the other issues I ran into, because I think a lot of the problems with D would go away if it had a large active community that would put the work in to maintain the D ecosystem, but that's a bit of a chicken and egg problem.

In the end, I decided that for me the reduced language overhead, solid ecosystem and modern conveniences of gnu17 C were more valuable in practice than the sweet features that D had to offer, and that made me a little sad, but I'm hopeful that one day D will make a strong comeback.

I know Walter gets notifications when D is mentioned on HN, and I imagine that if he read through this he'd shake his fist at me for saying interop-so-good-its-bad, but, if I could make a parallel with Java, I'd say that in code that uses many 3rd party libraries, D feels a bit like coding with JNI all the time (sorry). Ironically, in my opinion, D would benefit from having a community that rewrote popular libraries, instead of primarily relying on C interop.

2 comments

The neato thing about obj.foo() goes even further. Ever seen code like:

    a(b(c(d(e),3))
? Not very readable. UFCS (Universal Function Call Syntax) enables it to be written as:

    e.d.c(3).b.a();
Reading it flows naturally left-to-right.
Thanks Walter, that's a great example and I like that, because parens are optional, it could also be written as

    e.d.c(3).b.a
which is even cleaner.

For those who are thinking UFCS is a trivial detail, consider that the shell and some other languages have pipe operators (|>) to make the code flow intuitively the same way as the data.

In my opinion, in a C-like language, managing to squeeze so much functionality out of the '.' operator without any downsides is the mark of a well thought out, elegant language.

Thank you for creating D.

It is cleaner, but unfortunately it is not explicit. It is a function or a variable? I used to love those things until I noticed its defects.

For example, in C++, a = b can invoke anything. Not sure it is a good idea (except for generic code, there it is useful).

Zig has a philosophy of nothing hidden that I think it is mostly good.

That said, I find D a very nice language, the only problems are:

1. small ecosystem 2. last time I tried, packaging of download and use was... improvable.

Isn't it amazing how the . operator can cleanly replace :: and -> too?
Absolutely! Speaking of operators, out of curiosity, what's the reason for using '!' with templates?

Naively, I would think that making template instantiation look the same as a function call would be a desirable feature, with ambiguous calls needing to be resolved by the user.

Not many characters left in ASCII. Reuse of an existing operator almost required. Binary operators cannot be use as it would be grammatical ambiguous and would need resolution at the semantic pass which is a big no-no (that's why C++ is so slow at compiling, it cannot be parsed without semantic analysis). This left only the two exlusively unary operators !, ~. As ~ was repurposed for string concatenation, only ! remained.

    templ!thing(a,b)   
I would have thought that templ(thing)(a,b) would have been a good solution, as it is what is used in the declaration/definition side of templates, but this would have made removing redundant () not possible in UFCS expressions.
i would have preferred:

    templ<thing>(a, b)

because with that:

    templ!thing(a, b)
is it a function?, or are you calling thing's function?

you can do:

    templ!(thing)(a, b)
but did you mean?:

    templ!(thing(a, b))()

i personally always use !(), no matter what, and it's annoying to type, i don't want to waste time constantly trying to figure out what is what, it's mentally draining
debugging has significantly improved, it works great for D types https://github.com/Pure-D/dlang-debug

kotlin became very useful for focusing on being able to consume Java code

it allowed them to have a huge presence on android, that's enabler

it profits Zig as well

not everything needs to be ranked #1 in TIOBE index

there is value in being the way it is, it's organic, and no companies get to control its faith

> the C interop is so good, that 1) most libraries provide a 1-1 translation of their C APIs, which ends up being ugly, non-idiomatic D that forces me to think in both C and D when coding;

what do you mean? it's the same, function and data

    struct Data {}

    do_this(&myData);

this is valid D, it's also valid C

the problem i think you have is you are abusing OOP and think it's the only way of doing things, which is wrong, and this explain the sad state of software nowadays ;)

but it's weird when you then say you decided to stick with C, you contradict with yourself

> ... you are abusing OOP and think it's the only way of doing things

> ... when you then say you decided to stick with C, you contradict with yourself

Figments of your imagination.

Thanks for your comment. Please rest assured I am not abusing OOP, and am absolutely not contradicting myself by choosing C.
those pretty-printers are useful, thanks!