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