エイリアスと文字列

今私達は配列が何かを知っていて、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.convtoメソッドを使うことで各種型は非常に簡単に他のものに変換できます:

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つのコードユニットを含むからです: 0x410x03 そして 0x08 です。これらの後ろの2つは単一のコードポイント (ダイアクリティカルマーク結合文字)を定義し、 walkLength (任意のレンジの長さを計算する標準ライブラリ関数)は合計2つのコードポイントを数えます。 最後に、byGraphemeはこれら2つのコードポイントが1つの表示される文字に組み合わさることを 認識するためにかなり高価な計算を実行します。

ユニコードの正しい処理は非常に複雑になりえますが、大抵の場合、Dデベロッパーは単にstring変数を 魔法のバイト配列として考え、標準ライブラリのアルゴリズムに頼ることで適切に仕事をこなすことができます。 要素(コードユニット)の列を望む人は、 byCodeUnitが使えます。

DにおけるオートデコーディングはUnicode gemsチャプターで詳細に説明されます。

複数行文字列

Dにおける文字列は複数行に続くことができます:

string multiline = "
This
may be a
long document
";

ドキュメント中に引用符がある場合は、Wysiwyg文字列(下記参照)か ヒアドキュメント文字列が利用できます。

Wysiwyg文字列

予約されたシンボルの面倒なエスケープを最小限に抑えるために生文字列を使うことができます。 生文字列はバックティック( `... ` )かr(aw)プレフィックス(r" ... ")を使い宣言することができます。

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

D言語はさらに多くの文字列を表現する方法を提供しています。 ぜひ調べてみてください。

掘り下げる

rdmd playground.d