今私達は配列が何かを知っていて、immutable
に触れて、基本型も見てきているので、
1行に2つの構造を導入してみましょう:
alias string = immutable(char)[];
string
という語はalias
文によって、immutable(char)
のスライスとして定義されています。
これは、一度string
が構築されるとその内容が再び変更されることはないということを意味します。
そして実はこれが2つ目に紹介するものです: UTF-8 string
へようこそ!
その不変性により、string
は異なるスレッド間で完璧に共有されます。
string
はスライスなので、メモリ割り当て無しで一部分を取り出すことができます。
例として標準関数
std.algorithm.splitter
は、メモリ割り当て無しに文字列を改行で分割します。
UTF-8 string
のほかに、さらに2つの型があります:
alias wstring = immutable(wchar)[]; // UTF-16
alias dstring = immutable(dchar)[]; // UTF-32
std.conv
のto
メソッドを使うことで各種型は非常に簡単に他のものに変換できます:
dstring myDstring = to!dstring(myString);
string myString = to!string(myDstring);
普通のstring
は8ビットユニコードコードユニット
の配列として定義されています。
文字列にはすべての配列操作が使えますが、それらは文字レベルでなくコードユニットレベルで働きます。
同時に、標準ライブラリのアルゴリズムは文字列を
コードポイントの列として解釈します。
明示的なstd.uni.byGrapheme
の使用により、
それらを書記素の列として扱うオプションもあります。
以下の簡単な例で解釈の違いを説明します:
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
ここでs
の実際の配列の長さは3で、これは3つのコードユニットを含むからです:
0x41
、0x03
そして 0x08
です。これらの後ろの2つは単一のコードポイント
(ダイアクリティカルマーク結合文字)を定義し、
walkLength
(任意のレンジの長さを計算する標準ライブラリ関数)は合計2つのコードポイントを数えます。
最後に、byGrapheme
はこれら2つのコードポイントが1つの表示される文字に組み合わさることを
認識するためにかなり高価な計算を実行します。
ユニコードの正しい処理は非常に複雑になりえますが、大抵の場合、Dデベロッパーは単にstring
変数を
魔法のバイト配列として考え、標準ライブラリのアルゴリズムに頼ることで適切に仕事をこなすことができます。
要素(コードユニット)の列を望む人は、
byCodeUnit
が使えます。
DにおけるオートデコーディングはUnicode gemsチャプターで詳細に説明されます。
Dにおける文字列は複数行に続くことができます:
string multiline = "
This
may be a
long document
";
ドキュメント中に引用符がある場合は、Wysiwyg文字列(下記参照)か ヒアドキュメント文字列が利用できます。
予約されたシンボルの面倒なエスケープを最小限に抑えるために生文字列を使うことができます。
生文字列はバックティック( `... `
)かr(aw)プレフィックス(r" ... "
)を使い宣言することができます。
string raw = `raw "string"`; // raw "string"
string raw2 = r"raw `string`"; // raw `string`
D言語はさらに多くの文字列を表現する方法を提供しています。 ぜひ調べてみてください。