First Impressions!

A Guy With an Opinion aguywithanopinion at gmail.com
Tue Nov 28 03:01:33 UTC 2017


Hi,

I've been using D for a personal project for about two weeks now 
and just thought I'd share my initial impression just in case 
it's useful! I like feedback on things I do, so I just assume 
others do to. Plus my opinion is the best on the internet! You 
will see (hopefully the sarcasm is obvious otherwise I'll just 
appear pompous). It would probably be better if I did a 
retrospective after my project is completed, but with life who 
knows if that will happen. I could lose interest or something and 
not finish it. And then you guys wouldn't know my opinion. I 
can't allow that.

I'll start off by saying I like the overall experience. I come 
from a C# and C++ background with a little bit of C mixed in. For 
the most part though, I work with C#, SQL and web technologies on 
a day to day basis. I did do a three year stint working with 
C/C++ (mostly C++), but I never really enjoyed it much. C++ is 
overly verbose, overly complicated, overly littered with poor 
legacy decisions, and too error prone. C# on the other hand has 
for the most part been a delight. The only problem is I don't 
find it to be the best when it comes to generative programming. 
C# can do some generative programming with it's generics, but for 
the most part it's always struck me as more specialized for 
container types and to do anything remotely outside of it's 
purpose takes a fair bit of cleverness. I'm sick of being clever 
in that aspect.

So here are some impressions good and bad:

+ Porting straight C# seems pretty straight forward. Even some of 
the .NET framework, like files and unicode, have fairly direct 
counterparts in D.

+ D code so far is pushing me towards more "flat" code (for a 
lack of a better way to phrase it) and so far that has helped 
tremendously when it comes to readability. C# kind is the 
opposite. With it's namespace -> class -> method coupled with 
lock, using, etc...you tend to do a lot of nesting. You are 
generally 3 '{' in before any true logic even begins. Then couple 
that with try/catch, IDisposable/using, locking, and then 
if/else, it can get quite chaotic very easily. So right away, I 
saw my C# code actually appear more readable when I translated it 
and I think it has to do with the flatness. I'm not sure if that 
opinion will hold when I delve into 'static if' a little more, 
but so far my uses of it haven't really dampened that opinion.

+ Visual D. It might be that I had poor expectations of it, 
because I read D's tooling was poor on the internet (and nothing 
is ever wrong on the internet), however, the combination of 
Visual D and DMD actually exceeded my expectations. I've been 
quite happy with it. It was relatively easy to set up and worked 
as I would expect it to work. It lets me debug, add breakpoints, 
and does the basic syntax highlighting I would expect. It could 
have a few other features, but for a project that is not 
corporate backed, it was really above what I could have asked for.

+ So far, compiling is fast. And from what I hear it will stay 
fast. A big motivator. The one commercial C++ project I worked on 
was a beast and could take an hour+ to compile if you needed to 
compile something fundamental. C# is fairly fast, so I've grown 
accustomed to not having to go to the bathroom, get a drink, 
etc...before returning to find out I'm on the linking step. I'm 
used to if it doesn't take less than ten seconds (probably less) 
then I prep myself for an error to deal with. I want this to 
remain.

- Some of the errors from DMD are a little strange. I don't want 
to crap on this too much, because for the most part it's fine. 
However occasionally it throws errors I still can't really work 
out why THAT is the error it gave me. Some of you may have saw my 
question in the "Learn" forum about not knowing to use static in 
an embedded class, but the error was the following:

Error: 'this' is only defined in non-static member functions

I'd say the errors so far are above some of the cryptic stuff C++ 
can throw at you (however, I haven't delved that deeply into D 
templates yet, so don't hold me to this yet), but in terms of 
quality I'd put it somewhere between C# and C++ in quality. With 
C# being the ideal.

+ The standard library so far is really good. Nullable worked as 
I thought it should. I just guessed a few of the methods based on 
what I had seen at that point and got it right. So it appears 
consistent and intuitive. I also like the fact I can peek at the 
code and understand it by just reading it. Unlike with C++ where 
I still don't know how some of the stuff is *really* implemented. 
The STL almost seems like it's written in a completely different 
language than the stuff it enables. For instance, I figured out 
how to do packages by seeing it in Phobos.

- ...however, where are all of the collections? No Queue? No 
Stack? No HashTable? I've read that it's not a big focus because 
some of the built in stuff *can* behave like those things. The C# 
project I'm porting utilizes queues and a specifically C#'s 
Dictionary<> quite a bit, so I'm not looking forward to having to 
hand roll my own or use something that aren't fundamentally them. 
This is definitely the biggest negative I've come across. I want 
a queue, not something that *can* behave as a queue. I definitely 
expected more from a language that is this old.

+ Packages and 'public import'. I really think it's useful to 
forward imports/using statements. It kind of packages everything 
that is required to use that thing in your namespace/package 
together. So you don't have to include a dozen things. C and C++ 
can do this with it's #includes, but in an unsatisfactory way. At 
least in my opinion.

- Modules. I like modules better than #include, but I don't like 
them better than C#'s namespaces. Specifically I don't like how 
there is this gravity that kind of pulls me to associate a module 
with a file. It appears you don't have to, because I can do the 
package thing, but whenever I try to do things outside that one 
idiom I end up in a soup of errors. I'm sure I'm just not use to 
it, but so far it's been a little dissatisfying. Sometimes I want 
where it is physically on my file system to be different from how 
I include it in other source files. To me, C#'s namespaces are 
really the standard to beat or meet.

+ Unit tests. Finally built in unit tests. Enough said here. If 
the lack of collections was the biggest negative, this is the 
biggest positive. I would like to enable them at build time if 
possible though.

- Attributes. I had another post in the Learn forum about 
attributes which was unfortunate. At first I was excited because 
it seems like on the surface it would help me write better code, 
but it gets a little tedious and tiresome to have to remember to 
decorate code with them. It seems like most of them should have 
been the defaults. I would have preferred if the compiler helped 
me and reminded me. I asked if there was a way to enforce them 
globally, which I guess there is, but I guess there's also not a 
way to turn some of them off afterwards. A bit unfortunate. But 
at least I can see some solutions to this.

- The defaults for primitives seem off. They seem to encourage 
errors. I don't think that is the best design decision even if it 
encourages the errors to be caught as quickly as possible. I 
think the better decision would be to not have the errors occur. 
When I asked about this, there seemed to be a disassociation 
between the spec and the implementation. The spec says a 
declaration should error if not explicitly set, but the 
implementation just initializes them to something that is likely 
to error. Like NaN for floats which I would have thought would 
have been 0 based on prior experiences with other languages.

- Immutable. I'm not sure I fully understand it. On the surface 
it seemed like const but transitive. I tried having a method 
return an immutable value, but when I used it in my unit test I 
got some weird errors about objects not being able to return 
immutable (I forget the exact error...apologies). I refactored to 
use const, and it all worked as I expected, but I don't get why 
the immutable didn't work. I was returning a value type, so I 
don't see why passing in assert(object.errorCount == 0) would 
have triggered errors. But it did. I have a set of classes that 
keep track of snapshots of specific counts that seems like a 
perfect fit for immutable (because I don't want those 'snapshots' 
to change...like ever), but I kept getting errors trying to use 
it like const. The type string seems to be an immutable(char[]) 
which works exactly the way I was expecting, and I haven't ran 
into problems, so I'm not sure what the problem was. I'm just 
more confused knowing that string works, but what I did didn't.

+- Unicode support is good. Although I think D's string type 
should have probably been utf16 by default. Especially 
considering the utf module states:

"UTF character support is restricted to '\u0000' <= character <= 
'\U0010FFFF'."

Seems like the natural fit for me. Plus for the vast majority of 
use cases I am pretty guaranteed a char = codepoint. Not the 
biggest issue in the world and maybe I'm just being overly 
critical here.

+ Templates seem powerful. I've only fiddled thus far, but I 
don't think I've quite comprehended their usefulness yet. It will 
probably take me some time to figure out how to wield them 
effectively. One thing I accidentally stumbled upon that I liked 
was that I could simulate inheritance in structs with them, by 
using the mixin keyword. That was cool, and I'm not even sure if 
that is what they were really meant to enable.

So those are just some of my thoughts. Tell me why I'm wrong :P


More information about the Digitalmars-d mailing list