Alias & Stringhe

Ora che sappiamo cosa sono gli array, abbiamo preso confidenza con immutable e abbiamo dato una rapida occhiata ai tipi base, è il momento di introdurre due nuovi costrutti in una riga:

alias string = immutable(char)[];

Il termine string è definito tramite un'istruzione alias che lo dichiara come una slice di immutable(char). Questo significa che, una volta creata, una string non potrà mai essere modificata. Ed è proprio questa la seconda novità importante: benvenute stringhe UTF-8!

Grazie alla loro immutabilità, le string possono essere condivise in modo sicuro tra thread diversi. Inoltre, essendo slice, è possibile estrarne porzioni senza allocare nuova memoria. Ad esempio, la funzione standard std.algorithm.splitter divide una stringa in base ai caratteri di accapo senza effettuare alcuna allocazione.

Oltre alla string UTF-8, ci sono altri due tipi:

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

Le varianti possono essere convertite facilmente tra loro usando il metodo to da std.conv:

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

Stringhe Unicode

Una string è definita come un array di code unit Unicode a 8 bit. Tutte le operazioni disponibili per gli array possono essere applicate alle stringhe, ma agiranno a livello di code unit e non di carattere. Gli algoritmi della libreria standard, invece, interpretano le string come sequenze di code point. È anche possibile trattarle come sequenze di grafemi utilizzando esplicitamente std.uni.byGrapheme.

Questo piccolo esempio illustra la differenza di interpretazione:

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

Qui la lunghezza effettiva dell'array s è 3, perché contiene 3 code unit: 0x41, 0x03 e 0x08. Gli ultimi due definiscono un singolo code point (carattere diacritico combinante) e walkLength (funzione della libreria standard per calcolare la lunghezza di un range arbitrario) conta due code point in totale. Infine, byGrapheme esegue calcoli piuttosto costosi per riconoscere che questi due code point si combinano in un singolo carattere visualizzato.

L'elaborazione corretta dell'Unicode può essere molto complicata, ma la maggior parte delle volte gli sviluppatori D possono semplicemente considerare le variabili string come array magici di byte e affidarsi agli algoritmi della libreria standard per fare il lavoro giusto. Se si desidera l'iterazione per elemento (code unit), si può usare byCodeUnit.

L'auto-decodifica in D è spiegata più in dettaglio nel capitolo sulle gemme Unicode.

Stringhe multi-linea

Le stringhe in D possono sempre estendersi su più righe:

string multiline = "
Questo
potrebbe essere un
lungo documento
";

Quando appaiono virgolette nel documento, si possono usare le stringhe Wysiwyg (vedi sotto) o le stringhe heredoc.

Stringhe Wysiwyg

È anche possibile utilizzare stringhe grezze per minimizzare il laborioso escaping di simboli riservati. Le stringhe grezze possono essere dichiarate usando sia i backtick ( ` ... ` ) sia il prefisso r(aw) (r" ... ").

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

D fornisce ancora più modi per rappresentare le stringhe - non esitare a esplorarli.

Approfondimenti

rdmd playground.d