Does D have too many features?
Jonathan M Davis
jmdavisProg at gmx.com
Sat Apr 28 16:56:52 PDT 2012
On Saturday, April 28, 2012 11:47:31 Walter Bright wrote:
> Andrei and I had a fun discussion last night about this question. The idea
> was which features in D are redundant and/or do not add significant value?
>
> A couple already agreed upon ones are typedef and the cfloat, cdouble and
> creal types.
>
> What's your list?
Well, that's a hard one. There isn't much in the language that I'd remove even
if we were doing a complete redesign without caring about backwards
compatibility. Most of the stuff that I'd change is already being (or has been)
changed. And while D isn't exactly big, it doesn't tend to have dark corners
like C++ does. I'm sure that I don't fully grasp everything in D, but it's
fairly rare that I run into something that surprises me or that I thought that
I understood but don't (though it still does happen sometimes). With C++, it
always feels like there's some new detail that pops up that I didn't have a
clue about - or that maybe I _did_ know about but had forgotten because of the
insane number of little details that C++ has.
One _big_ difference between D and C++ as far as complexity goes is that in
C++, a _lot_ of the complexity comes from weird things in the language and
knowing about how certain things can go horribly wrong (e.g. I can never
remember all of the details on how horribly broken multiple inheritence is).
It's frequently not an issue of knowing how to do things in the language but
rather an issue of knowing what weird side effects an problems happen with
certain stuff. With D, on the other hand, the complexity tends to be in just
knowing what all of the features are and what they can do.
The only feature that comes to mind as probably being overly complex is is
expressions, but that complexity can really come in handy sometimes.
std.traits should probably do more to alleviate the need for is expressions
though so that odds of needing some of the more complicated stuff are lessened.
* As for redundant features, the first one that really comes to mind is WYSIWYG
string literals. There are what, 4 different types of delimiters for string
literals? I don't even remember all of the options. I just always use ` if I
don't want any escaping in string literal and " if I do. The others may be
valuable enough to have in some contexts, but I _never_ use them.
* version vs static if seems kind of redundant, but it isn't really. version
is used for a very specific subset of conditional code compilation, and you can
define versions on the command line, whereas static if generally checks code
properties (like if a type meets certain conditions). So, I think that they
should probably be left as is. There would be some value in allowing a list of
versions to be given (rather than using logical operators) in order to avoid
duplicate code - e.g.
version(linux, FreeBSD)
{}
else version(MacOSX)
{}
else version(Windows)
{}
else
static assert(0);
but that's about the only thing that I'd change with version. And I wouldn't
want to get rid of it.
* foreach_reverse is essentially redudant at this point (not to mention
confusing if combined with delegates), since we have retro. But we might
already be planning to get rid of that. I'm not sure though.
* I hate C style struct initializers and would really like to see them go, but
for reasons that I don't understand, people actually use them rather than
using a proper constructor call, so I doubt that we could get rid of them
without a fair bit of complaining. I think that they're completely redundant
and very _un_D.
* There seem to be too many ways to do variadic functions. We have to allow C
style variadics for extern(C), but having 3 of our own seems like a bit much.
Variadic templates are generally all that we need. The others don't seem
necessary for the most part. But unfortunately, they should probably be left
in so that classes can use them with virtual functions, since they can't use
templates.
* As for features that add little value, the first one that comes to mind is
with. I think that I've used it all of once, and I don't think that I've seen
it in other people's code very often. It's hard to grep for (since with is
used in comments quite often), but it wouldn't surprise me at all if Phobos
doesn't use it at all. Also, I fear that not only does it add little value but
that it has a tendency to make code less readable.
* Increasingly, I don't like UFCS. I think that in most cases, it complicates
code for little value. And I _really_ don't like how it results in people
flipping chains of a(b(c(d(5)))) calls into something like d(5).c().b.().a(). I
think that it makes the code way harder to read. The code is completely
backwards. But I appear to be in the minority with that opinion. I also don't
like how it creates so many ways to write exactly the same code. It harms
readibility. But as much as I dislike many of the applications of UFCS, it
_does_ appear to be quite popular. And upon occasion, it may be useful, but I
_am_ wishing that we hadn't added it.
There are definitely features that I never use (e.g. opDispatch), but for the
most part, I think that they're stuff that adds real value for certain types of
stuff that I just don't do, so removing them wouldn't really make any sense.
Overall, I think that D's feature set is fairly solid. It's mostly just the
implementation of said features which is a problem - though some minor tweaks
are probably in order (e.g. as Bearophile suggests, make it so that adjacent
string literals don't concatenate).
- Jonathan M Davis
More information about the Digitalmars-d
mailing list