Alias & Strings

Nun, da uns Arrays bekannt sind und wir mit den Basis-Typen und dem Schlüsselwortimmutable beschäftigt haben, wird es Zeit zwei neue Konstrukte in einer Zeile einzuführen:

alias string = immutable(char)[];

Der Begriff string wird durch das Schlüsselwort alias definiert, und zwar als Slice bestehend aus immutable(char)s. Das bedeutet, sobald ein string konstruiert wurde, wird sich sein Inhalt nie mehr ändern. Und damit sind wir bei dem zweiten Konstrukt: Willkommen UTF-8 string!

Aufgrund ihrer Unveränderlichkeit (engl.: immutablility) können strings über verschiedene Threads hinweg geteilt werden. Da string ein Slice ist, können Teile ohne Speicher-Allokationen entnommnen werden. Die Standard-Funktion std.algorithm.splitter](https://dlang.org/phobos/stdalgorithmiteration.html#.splitter) z.B. teilt einen String anhand von Zeilensprüngen (newline-Zeichen) ohne jede Speicher-Allokation.

Neben dem UTF-8 string gibt es zwei weitere Typen:

alias wstring = immutable(wchar)[]; // UTF-16
alias dstring = immutable(dchar)[]; // UTF-32

Diese Varianten können durch Nutzung der to-Methode aus std.conv einfach ineinander konvertiert werden:

dstring myDstring = to!dstring(myString);
string myString   = to!string(myDstring);

Unicode Strings

Ein einfacher string ist als ein Array aus 8-bit Unicode code units definiert. Alle Array-Operationen können auf Strings angewandt werden, aber dies wird nur auf der Code-Unit-Ebene funktionieren, nicht aber auf Zeichen-Ebene! Gleichzeitig interpretieren die Algorithmen der Standard-Bibliothek Strings als Sequenzen aus Code Points. Darüber hinaus gibt es die Option der Behandlung der Sequenz als Grapheme durch explizite Nutznung von std.uni.byGrapheme.

Diese kleine Beispiel verdeutlicht die unterschiedlichen Interpretationen:

string s = "\u0041\u0308"; // Ä

writeln(s.length); // 3

import std.range : walkLength;
writeln(s.walkLength); // 2

import std.uni : byGrapheme;
writeln(s.byGrapheme.walkLength); // 1

Hier ist die tatsächliche Länge des Arrays s 3, weil es 3 Code Units enthält: 0x41, 0x03 and 0x08. Von diesen definieren zwei einen einzelnen Code Point (kombinierende diakritische Zeichen) und walkLength (Funktion der Standard-Bibliothek zur Berechnung der Länge beliebiger Ranges) zählt zwei Code Points. Schließlich ermittelt byGrapheme in einer aufwändigeren Berechnung, dass sich diese beiden Code Points zu einem einzigen angezeigten Zeichen zusammensetzen. Korrekte Unicode-Verarbeitung kann sehr kompliziert sein. Trotzdem dürfen D-Entwickler String-Variablen als magische Byte-Arrays betrachten und sich darauf verlassen, dass die Standard-Bibliothek "das Richtige tut". Die meiste Unicode-Funktionalität wird in dem Modul std.uni bereitgestellt, Grundlegenderes in std.utf.

Mehrzeilige Strings

Für die Erzeugung mehrzeiliger Strings bietet sich die string str = q{ ... }-Syntax an:

string multiline = q{ This
    may be a
    long document
};

Raw Strings

Auch ist es möglich Raw Strings zu benutzen, um die aufwändige Verarbeitung von reservierten Symbolen zu minimieren. Raw Strings können mittels Backticks (invertierte Hochkommanta) ( ` ... ` ) oder den r(aw)-Präfix (r" ... ") deklariert werden.

string raw  =  `raw "string"`; // raw "string"
string raw2 = r"raw "string";  // raw "string"

Weiterführendes

rdmd playground.d