The D Programming Language

Familiarize yourself with the powerful compiled and managed language D.

During the past few decades, programming languages have come a long way. In comparison to the dawn of UNIX
and C, when compiled languages were just getting their start, today's world is full of languages with all sorts of
goals and features. In this article, I discuss one such language, D from Digital Mars. D is a natively compiled,
statically typed, multiparadigm C-like language. Its aim is to simplify development of any type of
application—from kernels to games—by combining the performance and flexibility of C with the
productivity-boosting factors of languages, such as Ruby and Python. It originally was conceived by Walter Bright,
the man who wrote the first ANSI C++ compiler for DOS. The reference compiler is freely downloadable for both
Windows and Linux, and the front end is licensed under a dual GPL and Artistic license.

GDC is a D compiler, which uses the GCC back end and is distributed under the GPL. D's features include the
lack of a preprocessor, a garbage collector, flexible first-class arrays, contracts, inline assembler and more.
With all this, it still maintains ABI compatibility with C, allowing you to use all your old C libraries from D
easily, with little work. The D standard library includes bindings to all standard C functions as well.

writef is D's typesafe version of printf; writefln adds a newline character at the end. Garbage collector D
includes an automatic garbage collector, relieving the programmer of the need to manage memory explicitly. This
allows programmers to focus more on the task at hand, as opposed to having to worry about the condition of each
memory chunk. Furthermore, it eliminates a whole class of bugs dealing with dangling pointers and invalid memory
references. In times when the GC would slow the application down, there is always the option of turning it off
altogether or using C's malloc and free for memory management.

Modules

In D, modules are imported using the import statement and have a one-to-one correspondence with source files,
with the period as the path separator. Each symbol within a module has two names: the name of the symbol and the
name of the symbol prefixed by the module name, which is called the fully qualified name or FQN. For example,
writefln can be referred to as writefln or std.stdio.writefln. For cases when the FQN is preferred, the static
import statement imports the module's symbols but avoids putting them into the global namespace. For example, both
the std.string and std.regexp modules include functions for find, replace and split. Because I'm more likely to use
pure string functions than regular expressions, I would statically import std.regexp, so that whenever I wanted to
use any of its functions, I would have to be explicit, whereas I simply could call the string functions by their
regular names.

Modules can have static constructors and destructors. The static this() function in any module is the static
constructor and is invoked before main(); after main has returned the static, ~this() function is invoked. Because
modules are imported symbolically, this means there are no header files. Everything is declared once and only once,
eliminating the need for declaring functions in advance or declaring classes in two places and trying to keep both
declarations consistent.

alias and typedef

In D, there is a distinction made between an alias and a type. A typedef introduces an entirely new type to
the type-checking system and to function overloading, which are discussed later. An alias is a simple replacement
for a type, or optionally a symbol:

In D, arrays are first-class types in every way. D contains three types of arrays: static, dynamic and
associative arrays. Array declarations read right to left; char[][] is interpreted as an array of arrays of
characters:

Dynamic and static arrays can be sliced with the .. operator. The starting parameter is inclusive, but the
ending parameter is not. Therefore, if you slice from zero to the length of an array, you get the whole array:

This is a prime example of how D implements a lot of syntactic sugar on top of more low-level routines to
make the programmer more focused on the implementation of the task itself. Strings D takes arrays one step further.
Because strings are logically arrays of characters, D has no built-in string type; instead we simply declare an
array of characters.

Furthermore, D has three types of strings: char, a UTF-8 codepoint; wchar, a UTF-16 codepoint; and dchar, a
UTF-32 codepoint. These types, along with standard library routines for manipulating unicode characters, make D a
language suited to internationalized programming. In comparison with C, D strings know their length, eliminating
even more bugs and security issues dealing with finding the elusive null terminator.

Why makes gc pure compiling (whatever that means) no longer true ? GC is done by the runtime and has nothing to do with compiling. D is a "pure compiling" language (as pure as you can get - there is nothing more pure than compiling into platform dependent native code). And why is a language badly designed just because it has the option to use garbage collection (in D you can manage memory by yourself and turn garbage collection completely off, if you want to) ?

Using ~ for concatenating arrays and not + makes sense because your not adding strings like you are adding numbers. But that might be just a matter of taste.

But if these two things are the only criterions for you to decide if a language is good or bad designed, you should better not become a language designer.

As always this is a matter of taste and personal preference. But C++ had to be designed to be backward compatible to C, so some things could not be as clean designed as they should be and make the language more complicated and error prone.

Trending Topics

Upcoming Webinar

Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report

August 27, 2015
12:00 PM CDT

DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.