Hauptmenü öffnen

D (Programmiersprache)

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.[7] Sie lehnt sich äußerlich stark an C++ an, jedoch ohne vollständige sprachliche Kompatibilität dazu.

D
D Programming Language logo.svg
Basisdaten
Paradigmen: imperativ, objektorientiert, funktional, parallel, generisch, modular
Erscheinungsjahr: 2007
Designer: Walter Bright
Entwickler: Walter Bright,
Andrei Alexandrescu (ab D 2.0)
Aktuelle Version: 2.088.0  (1. September 2019[1])
Typisierung: Stark, statisch
Wichtige Implementierungen: DMD, GDC, LDC
Beeinflusst von: C, C++, Eiffel, Java, C#, Python, Ruby[2]
Beeinflusste: DScript, Genie, MiniD, Qore, Swift, Vala
Betriebssystem: Plattformunabhängig
Lizenz: Boost Software License[3][4][5][6]
dlang.org

Vom 17. Juni 2007 bis Ende 2010 wurde die Version 2 von D entwickelt, die neue Funktionalität wie Closures und pure Funktionen sowie das funktionale Paradigma ergänzt, aber nicht kompatibel zur Vorgängerin 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.

SprachmittelBearbeiten

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.[8]

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.[9][10] Automatische Referenzzählung wird hingegen nicht unterstützt.[11]

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.

CompilerBearbeiten

DMD, der Digital Mars D-Compiler,[12] 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[13] sowie LDC,[14] 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[15] und Dang,[16] die kompatibel zu LLVM sind. Ein Codegenerator für die .NET-Plattform stellt eher einen Machbarkeitsnachweis dar als einen funktionstüchtigen Übersetzer.[17] Seit Version 9.1 des GCC wird die Sprache D unterstützt[18]

EntwicklungsumgebungenBearbeiten

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,[19] für MonoDevelop gibt es Mono-D.[20]

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.[21][22]

ProgrammbeispielBearbeiten

Hallo Welt
Ausgabe der Kommandozeilenparameter
// Programm, geschrieben in D2, das seine Parameter ausgibt
// importiert writefln aus dem Modul std.stdio
import std.stdio : writefln;

void main(string[] args) {
    // Jeder Eintrag im Feld args wird ausgegeben.
    foreach(i, arg; args)
        writefln("Parameter %d = '%s'", i, arg);
}

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:

Parameter 0 = 'beispiel.exe'
Parameter 1 = '-win'
Parameter 2 = '-s'
Unittests

Unittests bzw. Modultests[23] 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[24] generierten Dokumentation aufgeführt werden. In D werden die Unittests unmittelbar vor der Main-Funktion ausgeführt.

/++
    Ermittelt, ob eine Zahl eine Primzahl ist.
    Hinweis: Das Verfahren ist nicht optimal.
Params:
    a: die zu testende Zahl
Returns:
    true, falls die Zahl eine Primzahl ist;
    false, ansonsten
+/
bool isPrime(long a) {
    if (a <= 1)
        return false;

    // falls a keine Primzahl ist und a restlos durch n teilbar ist
    for (long n = 2; n <= a / 2; ++n)
        if (a % n == 0)
            return false;

    // a war nicht teilbar -> a muss eine Primzahl sein
    return true;
}

unittest {
    // Die Bedingung in dem Assert-Aufruf muss erfüllt werden (wahr sein).
    // Sonst ist ein Fehler aufgetreten und das Programm bricht ab.
    assert(isPrime( 0) == false);
    assert(isPrime( 1) == false);
    assert(isPrime( 2) == true);
    assert(isPrime( 7) == true);
    assert(isPrime( 4) == false);
    assert(isPrime(10) == false);

    // Hier wird erwartet, dass der Test fehlschlägt, da 11 prim ist.
    // Fehlerhafter Code: Assert schlägt immer fehl!
    assert(isPrime(11) == false);
}

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 ProgrammierungBearbeiten

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

Funktionstemplates
// Diese Funktion liefert als Return-Wert das Maximum der beiden Parameter
// Der Template Datentyp T wird dabei automatisch (falls möglich) erkannt
T max(T)(T a, T b) {
    if( a < b )
        return b;
    else
        return a;
}

unittest {
    assert(max(2, 3) == 3);
    assert(max('a','c') == 'c');
    assert(max(3.1415, 2.61) == 3.1415);
    assert(max("Hallo", "Abc") == "Hallo");
}
Meta-Programmierung
// Berechnet das Ergebnis von basis^exp
template Pow(double basis, uint exp) {
    static if (exp > 0)
        enum Pow = basis * Pow!(basis, exp-1);
    else
        enum Pow = 1;
}

import std.stdio;

void main() {
    // Da pow ein Template ist, wird das Ergebnis zur Compilezeit bestimmt
    // und steht zur Laufzeit als Konstante zur Verfügung

    writeln("2.7182^3 = ", Pow!(2.7182, 3));
    writeln("3.1415^5 = ", Pow!(3.1415, 5));
}

Ausgabe:

2.7182^3 = 20.0837
3.1415^5 = 305.975
Compile Time Function Execution

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

T sum(T)(T[] elems) {
    T res;
    
    foreach(elem; elems)
        res += elem;
    
    return res;
}

enum arr = [10, 13, 14, 15, 18, 19, 22, 24, 25, 36];
// summeVonArr ist zur Kompilierungszeit bekannt.
enum summeVonArr = sum(arr); // == 196

// Statisches Integer-Array mit der Laenge 196
int[summeVonArr] staticArray;

LiteraturBearbeiten

WeblinksBearbeiten

EinzelnachweiseBearbeiten