D (Programmiersprache)
# D (Programmiersprache)

D ist eine seit 1999 von Walter Bright entwickelte Programmiersprache mit objektorientierten, imperativen sowie deklarativen Sprachelementen. D wurde am 3. Januar 2007 in der stabilen Version 1.0 veröffentlicht. Sie lehnt sich äußerlich stark an C++ an, jedoch ohne vollständige sprachliche Kompatibilität dazu.

Vom 17. Juni 2007 bis Ende 2010 wurde die Version 2 von D entwickelt, die neue Funktionalität wie Closures und dem Begriff referentiell transparenter Funktionen sowie das funktionale Paradigma ergänzt, aber nicht kompatibel zum Vorgänger ist. Mit der Freigabe der neuen Version wurde auch das Buch The D Programming Language von Andrei Alexandrescu veröffentlicht, der entscheidend beim Design der Sprache mitwirkte.

## Sprachmittel

D übernimmt die meisten Sprachmittel der Sprache C, verzichtet im Gegensatz zu C++ aber auf die Kompatibilität dazu. Dadurch soll die Übernahme von Entwurfsnachteilen vermieden werden. Durch ABI-Kompatibilität sind aber trotzdem alle in C geschriebenen Programme und Bibliotheken nutzbar. Die Anbindung von C++-Code unterliegt dagegen Einschränkungen.

D ist eine objektorientierte, imperative Programmiersprache, die ab D 2.0 auch Möglichkeiten der funktionalen Programmierung innerhalb einer imperativen Programmiersprache bietet, und verfügt über Klassenvorlagen und überladbare Operatoren. D bietet Design by contract und Module. Automatische Speicherbereinigung ist im Gegensatz zu z. B. C/C++ fester, wenn auch prinzipiell optionaler Bestandteil der Sprache, wobei geplant ist, die Laufzeitumgebung selbst insoweit von dieser zu entkoppeln, dass ein Arbeiten mit D auch in Situationen möglich ist, wo der Einsatz eines Garbage Collectors unmöglich oder unerwünscht ist. Automatische Referenzzählung wird hingegen nicht unterstützt.

Programme können in D ohne Zeiger geschrieben werden. So bestehen Felder transparent sowohl aus dem Ort ihrer Daten als auch aus ihrer Länge, wodurch Zeigerarithmetik überflüssig ist und die Zulässigkeit von Feldzugriffen zur Laufzeit überprüft werden kann. Im Gegensatz zu Java ist es aber dennoch möglich, Zeiger bei Bedarf nahezu wie in C zu benutzen und so maschinennah zu programmieren.

### Konstante und schreibgeschützte Werte

In D werden schreibgeschützte Werte mit const-Datentypen ausgezeichnet. Schreibgeschützt heißt, dass über diese Variable der Wert nicht verändert werden kann. Das bedeutet jedoch nicht, dass es keine andere Variable gibt, über die eine Änderung stattfinden kann. Dem gegenüber stehen (wirklich) konstante Werte, die mit immutable-Datentypen ausgezeichnet werden. Ist ein Wert immutable, gibt es überhaupt keine schreibbare Variable auf den Wert.

### Funktionsattribute

In D werden Funktionen mit Funktionsattributen versehen, um anzuzeigen, dass die entsprechende Funktion gewisse Garantien macht (oder auch nicht). Folgende Attribute stellen Garantien dar:

* pure zeigt an, dass die Funktion referentiell transparent ist.
* nothrow zeigt an, dass die Funktion keine Exception wirft (möglicherweise aber einen Error).
* @nogc zeigt an, dass die Funktion keinen Speicher von der automatischen Speicherverwaltung anfordert und daher keine automatische Speicherbereinigung (Garbage Collection) auslösen kann.
* @safe zeigt an, dass die Funktion keine Speicherzugriffsverletzung auslösen kann, die zu undefiniertem Verhalten führt.
* @live zeigt an, dass die Funktion das Ownership-Borrowing-Modell für die Speicherverwaltung verwendet.

Zu @safe gehören die Attribute @system und @trusted. Unter anderem unterliegen mit @safe gekennzeichnete Funktionen der Beschränkung, nur andere solche Funktionen aufrufen zu dürfen, sowie solche mit @trusted. Mit @trusted oder @system gekennzeichnete Funktionen dürfen jedoch beliebige Anweisungen ausführen. Nicht explizit gekennzeichnete Funktionen sind implizit @system.

Normalerweise arbeitet ein Großteil des Programms innerhalb der Grenzen von @safe. Da sich D als Systemprogrammiersprache versteht, wird dem Programmierer nicht die Möglichkeit verwehrt, Anweisungen auszuführen, deren Freiheit von möglichen Speicherzugriffsverletzungen sich der Prüfung durch den Compiler entzieht. Typischerweise ist eine Funktion @system, wenn sie Speicherzugriffsverletzungen auslöst, wenn sie falsch benutzt wird. Mit @trusted ausgezeichnete Funktionen bilden eine Zwischenschicht, die @system Code nutzt, aber auf eine Weise, die bekanntermaßen keine Speicherzugriffsverletzungen auslöst. Das wird vom Compiler jedoch nicht maschinell geprüft und es obliegt dem Programmierer oder der Qualitätssicherung, nachzuweisen, dass der @system korrekt verwendet wird.

Ein Beispiel dafür ist die C-Funktion memcpy, die n Bytes von A nach B kopiert. Ist der Puffer B nicht groß genug, die n Bytes aufzunehmen, ist eine Speicherzugriffsverletzung möglich. Daher ist Anbindung von memcpy in D @system. Ein geeigneter D-Wrapper nimmt zwei sog. Slices an statt zweier Zeiger und einer Anzahl. Slices bestehen aus einem Zeiger und einer Länge; es kann also überprüft werden, ob der annehmende Puffer groß genug ist. Ein Wrapper, der einen geordneten Programmabsturz herbeiführt, darf somit mit @trusted annotiert werden. Bei Testläufen sollten Falschverwendungen des Wrappers sofort ersichtlich werden.

Ein weiteres Beispiel sind Funktionen mit Inline-Assembler-Blöcken, da diese sich grundsätzlich einer Überprüfung durch den Compiler entziehen. Möglicherweise ist jedoch offensichtlich, dass ein solcher Block keine unsicheren Speicheroperationen durchführt. Auch dann ist die Annotation @trusted korrekt und sinnvoll.

## Compiler

DMD, der Digital Mars D-Compiler, ist die Referenzimplementierung von Walter Bright und für die x86/x86-64-Versionen von Windows, Linux, macOS und FreeBSD erhältlich.

Die wichtigsten Übersetzer mit alternativen Backends sind der auf GCC aufbauende GDC sowie LDC, das sich auf die Qualitäten von LLVM stützt. Neben der hohen Geschwindigkeit des generierten Maschinencodes ermöglichen diese Backends außerdem die Bedienung von x86-64- und verschiedener anderer Architekturen.

Inzwischen wurden auch zwei Compiler für D in D selbst programmiert: Dil und Dang, die kompatibel zu LLVM sind. Ein Codegenerator für die .NET-Plattform stellt eher einen Machbarkeitsnachweis dar als einen funktionstüchtigen Übersetzer. Seit Version 9.1 des GCC wird die Sprache D unterstützt.

## Entwicklungsumgebungen

D wird zunehmend von verschiedenen IDEs unterstützt. Zum Einsatz kommen unter anderen die Editoren Entice Designer, Emacs, Vim, Scite, Scite4D, Smultron, TextMate, Zeus, Geany und Visual Studio Code. Vim und Scite4D unterstützen Syntaxhervorhebung und Autovervollständigung. Für TextMate und Visual Studio Code existiert jeweils eine Erweiterung, auch Code::Blocks unterstützt D teilweise.

Darüber hinaus gibt es noch Plug-ins für andere IDEs: Eclipse unterstützt D mit dem Plug-in DDT, für MonoDevelop gibt es Mono-D.

Zudem gibt es in D geschriebene IDEs, wie Poseidon, das Autovervollständigung sowie Refactoring unterstützt und einen integrierten Debugger hat. WinDbg und der GNU Debugger unterstützen D rudimentär.

## Programmbeispiele

### Ausgabe der Kommandozeilenparameter

Die Annotation @safe bedeutet, dass die Funktion frei von Speicherzugriffsverletzungen ist und der Compiler das überprüfen wird. Sie ist nicht notwendig, aber sinnvoll.

Der main-Funktion werden die Kommandozeilenparameter als ein Feld von Zeichenketten (Strings) übergeben. Ruft man dieses Programm unter Windows mit beispiel.exe -win -s auf, dann gibt es diesen Text in einem Konsolen-Fenster aus:

### Unittests

Unittests bzw. Modultests sind Blöcke, die Programmcode enthalten, welcher eine Funktion auf unterschiedliche Fälle testen soll. Zusätzlich kann der in Unittest-Code als Beispiel in der von DDOC generierten Dokumentation aufgeführt werden. In D werden die Unittests unmittelbar vor der Main-Funktion ausgeführt.

Die Annotation pure bedeutet, dass isPrime eine referentiell transparente Funktion ist, ihr Ergebnis also nur von den Eingaben, aber nicht von globalen Variablen abhängt. Der Compiler überprüft die Korrektheit der Annotation.

Unittests sind Testfunktionen, die das Verhalten einer Funktion auf alle Möglichkeiten testen sollen. Damit Unittests ausgeführt werden, muss ein Compiler-Flag gesetzt werden (-unittest bei DMD).

### Generische Programmierung

Zusätzlich zu Mixin-Templates implementiert die Programmiersprache D alle gängigen Templatearten.

**Meta-Programmierung**

Ausgabe:

**Compile Time Function Execution**

Mit noch während der Kompilierung ausgeführten Funktionen (CTFE) können Initialisierungslisten, Lookup-Tables u. Ä. erstellt und durch sog. Mixins bei der Übersetzung aus Strings generierter D-Code eingebunden werden. Diese beiden Features bieten eine Möglichkeit für die Realisierung domänenspezifischer Sprachen in D.

Die Initialisierung von result mit null ist notwendig, falls T durch einen Fließkomma-Datentyp wie double belegt wird, denn uninitialisierte Fließkommazahlen-Variablen werden mit NaN initialisiert, statt mit null.

