C has a long
and venerable history. But Can a language written in the
1970s work thirty years on?
Dermot Hogan considers
whether D is a worthy successor to C...?
There have been several evolutions
of the C language – Objective
C, C++, Java, C# to name but the major ones. Each has
added on something to the basic C structure, with more
or less success; and each has been defined by its time
(and what was capable of running efficiently on a machine
of that time).
It seems to me that C++ hasn’t been so much designed
as ‘grown’ – and not very successfully
at that. But no one, as far as I am aware, has sat
down and carefully looked at the core of C and tried
to figure out the good and bad parts and, more importantly,
which features from other languages might be successfully
grafted onto the core language. Until a few years ago
that is: enter Walter Bright with the D language.
Just so you know where I stand on the matter: I like
C. The original, that is. I regularly program in C on
Microchip dsPIC devices and for that for that sort of
thing it’s the ideal language. But I have to admit
that straight C on a 3GHz processor with 1.5GB of memory
and a 200GB disk on a PC running Windows XP just isn’t
efficient. Don’t get me wrong – in one sense
C is wonderfully efficient – as it can be
used to write fast-running code. But for programming
a modern GUI and the rest, it’s terrible – it’s
far too low level. In that sense, it’s inefficient
because it wastes so much of my time!
But the main alternative to pure C, C++, sucks: it has
no ‘conceptual integrity’, an idea I’ll
come back to later. On the other hand, C# and Java aren’t
really C. I treat C# as being a mechanism for implementing
Microsoft’s .NET framework; Java I have no use
for – I don’t write in Cobol, either of the
old or new variety. And since Microsoft, in its
wisdom, has recast Visual Basic as an inferior C#, that’s
no longer in the frame, either.
D, though, looks interesting. It is C, or at
least, a close relative – but not a compatible
superset like Objective C or a series of ad-hoc ‘patches’ as
in C++. Instead, it’s a rewrite of C but aimed
at systems programming rather than application
level work. I’ll pick out some of the interesting
features here. For a full list, you’ll need to
download the (very readable) manual from www.digitalmars.com.
My Picks...
First, D is object oriented. Not like Smalltalk where
everything is an object or even C# where most things
are objects. It’s object oriented in a sensible,
practical sort of way. Object orientation is treated
as a tool, not as the Word Of God. For example, classes
are classes, as in other languages, but with single
inheritance. But structs are what they should be: record
layouts. If you’ve ever tried to use C# or Visual
Basic .NET to talk to a micro-controller – and
I have - you’ll appreciate the problem. A struct
should be an unmanaged memory tool, otherwise what
use is it? You might as well use a class. The C# distinction
between stack allocation and heap allocation is worthless.
Secondly, D uses managed memory and garbage collection.
This means that, for most of the time, you can forget
about freeing stuff up. I’ve just waded through
a Microsoft example C++ program (dealing with Visual
Studio debugging extensions, if you really want to know)
where every bit of memory was tediously allocated and
then freed. I’d
forgotten just how time consuming it is just writing
C++ code – let alone debugging it.
And now a subject close to my heart. Engraved on it
almost: COM. Currently, from Microsoft’s perspective,
COM is sort of ‘undead’. Few in Microsoft
seem to acknowledge its existence, but it’s there
all the same. All pervasive, in fact. Now, there are
good bits to COM and there are bad bits. The good bits
are the way the interface definitions work – ‘austere’ is
a good description. The bad bits are the threading and
apartment models – ‘baroque’, I think,
is an appropriate term. COM was supposed to have gone
away with .NET, but it most certainly hasn’t. I’ve
been recently programming some Visual Studio extensions
(using the good bits of COM) and I can tell you that
COM is alive and well and living in Visual Studio. And
in many other Microsoft products too.
The problem is that programming COM from a managed tool
like C# isn’t always that easy. Sure, it’s
simple enough to define the interface, and the Visual
Studio 2005 IDE makes it easy to knock out a boilerplate
implementation. The trouble comes from the fact that
C# also defines its own interfaces – which
aren’t necessarily COM ones. I also don’t
like the rather kludgey way that you implicitly use QueryInterface
by casting. It all works, but it’s not elegant
and you do have to keep littering your C# code with Guid
and COM attributes. In contrast, a D interface is pretty
much the same as a COM type interface – a set of
pointers into an external DLL. Further, all D objects
with a COM interface (derived from IUnknown) are automatically
COM objects. In other words, you can use COM cleanly
and explicitly from D.
Additionally, casting is far more intelligently used.
In C#, a cast is typically either a call to QueryInterface
or it’s used to up-cast or down-cast as required.
Or even as in the original C to tell the compiler to
stop moaning and just do it. D introduces a new cast operator
which makes it very clear that you are requesting the
compiler to cast; cast has the bonus
that you can search for all casts using a text editor.
Neat.
Installation
Lastly, let's talk about the rather peculiar installation
procedure. There isn’t one. You just unzip the
download into a directory of your choice and path it
(if you want to). That’s it. No registry entries,
no installation wizard – just unzip and go. And
it works too - much to my surprise. It harks back to
a simpler, earlier era of programming. After weeks of
doing battle with Visual Studio and the registry, I don’t
think that’s
a bad thing at all.
Ah! The good old days!
A DOS box, a text editor and a C compiler (here,
in fact, a D compiler) …it
takes me back. I got quite misty eyed over
this example. |
Other goodies
There’s an awful lot in D, so it’s difficult
in a short article to cover everything, so here’s
a list of some of the other features that caught my eye:
- Nested functions. Yes – you can have a function
enclosed within a function. Originally, C didn’t
include these for efficiency reasons. However, there’s
no a priori reason why you shouldn’t have these
or use them.
- Delegates. A delegate is a function pointer with
an object reference. I’ve never been able to
figure out why Java doesn’t have them. And yes,
I’ve read Sun’s ‘justification’
of why delegates are A Bad Thing. It strikes me as
total garbage: delegates just make life easier.
- Operator overloading. The only examples I’ve
seen of operator overloading in C++ produced unreadable
code. Elegant, but unreadable: try figuring out celestial
mechanics when you have to keep working out what the
[] operator is doing. It’s not easy, I can tell
you. Still, should you wish to use operator overloading,
you can.
- Templates. I’m a recent convert to templates
and I think that any C type language must have them.
D has them.
Downsides
Actually, these aren’t downsides so much as the
natural consequences of having flexibility and of D being
aimed at ‘systems programming’. The first
issue is pointers. D is not a ‘safe’ language
like Java or C#. You can futz about with pointers far
more easily than you can in C# (in Java you can’t – end
of story). The problem comes with the garbage collector
collecting things that you’ve messed with. If you
have so messed, disaster will pretty quickly follow.
However, the upside to this is that you can allocate
memory by using malloc and if you are careful, you can
avoid the use of the garbage collector completely. This
means that you can implement a real-time – defined
as responding to an event within a predetermined time – system
in D. You simply cannot do this in C# or Java. This may
not be important to most people, but to me it is. I’ve
recently written a real-time telescope controller and
in this type of application, you simply cannot – cannot – wait
for a few milliseconds while a garbage collection occurs.
The heavens don’t stop moving because you’ve
run out of memory.
But there are no regular expressions in D! Admittedly,
this is a personal beef. And I’d have to allow
that those who think that regular expressions have no
place whatsoever in a systems programming language
have a point. But once you’ve used Perl or Ruby,
where regular expressions are ‘first class objects’,
than you really miss them in other languages.
Lastly, I also have my doubts about D’s ‘contracts’.
A D contract is an assertion that something is or isn’t
the case. For example, that a number is greater than
zero when a square root operation occurs. D builds these
assertions into the language. Contracts (in general – they
also occur in Chrome and Eiffel) seem to me to be just
one more ‘magic bullet’ that will lead to
the promised land of bug free programming. I remain sceptical.
Summary
There’s something I like about Walter Bright (the
man behind D) – he’s straightforward in
his views. For example, on C tags: “This
misfeature of C is where the tag names of structs are
in a separate but parallel symbol table. C++ attempted
to merge the tag name space with the regular name space,
while retaining backward compatibility with legacy C
code. The result is not printable.” You know where
you stand with this guy.
D is the evolution of Mr. Bright’s considerable
expertise in the practical implementation of C and C++
compilers. He knows what works and what doesn’t.
With D, he seems to have distilled many years of experience
into a practical re-write of the original C language.
One way of viewing D is as ‘C done right’.
Earlier I used the term ‘conceptual integrity’.
This comes from ‘The Mythical Man Month’ by
Fred Brookes. He uses it to distinguish the excellent
from the indifferent. Good systems and designs have it;
bad ones don’t. Naturally, C++ doesn’t have
conceptual integrity.
On the other hand, D isn’t merely good; D has
conceptual integrity.
See also our interview
with Walter Bright - creator of the D language
May 2006 |