リテラル

プログラムは、変数やオブジェクトの値を操作することで、そのタスクを実行する。変数やオブジェクトは、関数や演算子を使って新しい値や新しいオブジェクトを生成する。

一部の値は、プログラムの実行中に生成する必要はなく、代わりにソースコードに直接記述される。例えば、浮動小数点値0.75string"Total price: "は、プログラムによって計算されない:

discountedPrice = actualPrice * 0.75;
totalPrice += count * discountedPrice;
writeln("Total price: ", totalPrice);
D

ソースコードに直接入力されるこのような値は、リテラルと呼ばれる。これまで作成したプログラムでは、多くのリテラルを使用してきた。ここでは、リテラルのすべての型とその構文規則について説明する。

整数リテラル

整数リテラルは、4つの方法のいずれかで記述することができる。1つは、私たちが日常的に使用している10進法、2つ目は、特定の計算作業に適した16進法と2進法、3つ目は、ごくまれに必要になる8進法である。

コードを読みやすくするために、整数リテラルの最初の桁の後に、_の文字を任意の場所に挿入することができる。例えば、1_234_567のように、3桁のグループを形成するために使用することができる。別の例としては、ある値を通貨のセント単位で測定し、199_99のように、通貨単位とセントを区切るために使用することができる。これらの文字はオプションであり、コンパイラでは無視される。

10進数系:リテラルは、12など、私たちが日常的に使用している10進数と同じ方法で指定する。Dで10進数系を使用する場合、最初の桁は0にはできない。このような先頭の0は、他のプログラミング言語では8進数を表すために使用されることが多いため、この制約により、見落としがちなこの違いによって生じるバグを防ぐことができる。ただし、0自体は使用できる。0は0だ。

16進数では、リテラルは0xまたは0Xで始まり、16進数の数字"0123456789abcdef"および"ABCDEF"を含む。0x12ab00feと同様である。

8進数システム:リテラルは、std.convモジュールからoctalテンプレートを使用して指定され、8進数の数字"01234567"が含まれる(octal!576を参照)。

2進数系:リテラルは0bまたは0Bで始まり、2進数の数字0および1を含みる。0b01100011のように。

整数リテラルの型

他の値と同様に、すべてのリテラルは特定の型を持つ。リテラルの型は、intdoubleなどとして明示的に指定されることはない。コンパイラは、リテラル自体の値と構文から型を推測する。

ほとんどの場合、リテラルの型は重要ではないが、使用されている式と型が一致しない場合がある。そんなときは、型を明示的に指定する必要がある。

デフォルトでは、整数リテラルはint型と推測される。値がintで表現できないほど大きい場合、コンパイラは次のロジックを使用してリテラルの型を決定する。

このロジックを実際に確認するために、typeofstringofを利用した次のプログラムを試しよう。

import std.stdio;

void main() {
    writeln("\n--- these are written in decimal ---");

    // intに適合するため、型はintになる
    writeln(       2_147_483_647, "\t\t",
            typeof(2_147_483_647).stringof);

    // intに適合せず、10進数であるため、型はlongになる
    writeln(       2_147_483_648, "\t\t",
            typeof(2_147_483_648).stringof);

    writeln("\n--- these are NOT written in decimal ---");

    // intに適合するため、型はintになる
    writeln(       0x7FFF_FFFF, "\t\t",
            typeof(0x7FFF_FFFF).stringof);

    // intに適合せず、10進数でもないため、型はuintになる
    writeln(       0x8000_0000, "\t\t",
            typeof(0x8000_0000).stringof);

    // uintに収まらず、10進数でもないため、型はlongになる
    writeln(       0x1_0000_0000, "\t\t",
            typeof(0x1_0000_0000).stringof);

    // longに収まらず、10進数でもないため、型はulongになる
    writeln(       0x8000_0000_0000_0000, "\t\t",
            typeof(0x8000_0000_0000_0000).stringof);
}
D
literals.1

出力:

これらは十進法で書かれている
2147483647int
2147483648long
これらは十進法で書かれていない
2147483647int
2147483648uint
4294967296long
9223372036854775808ulong
Lの接尾辞

値の大きさは関係なく、10LのようにLで終わる場合、型はlongになる。

Uサフィックス

リテラルが10UのようにUで終わる場合、その型は符号なし型になる。小文字のuも使用できる。

LおよびU指定子は、任意の順序で一緒に使用することができる。例えば、7ULおよび8LUは、どちらも型ulongである。

浮動小数点リテラル

浮動小数点リテラルは、1.234のように10進数で指定することも、0x9a.bcのように16進数で指定することもできる。

10進法: eまたはEの後に指数を付加して、"10の累乗"を意味することができる。例えば、3.4e5は"3.4 ×10の5乗"、つまり340000を意味する。

指数値の前に"-"文字を入力すると、その意味は"10の累乗で割る"に変わる。例えば、"7.8e-3"は"7.8を10の累乗で割る"という意味になる。指数値の前に"+"文字を指定することもできるが、この場合は何の意味もない。例えば、"5.6e2"と"5.6e+2"は同じ意味になる。

16進数では、値は0xまたは0Xで始まり、小数点の前と後の部分は16進数の数字で指定する。eおよびEはこのシステムでは有効な数字であるため、指数はpまたはPで指定する。

もう1つの違いは、指数は"10の累乗"ではなく、"2の累乗"を意味することだ。例えば、0xabc.defP4P4部分は"2の4乗"を意味する。

浮動小数点リテラルにはほとんどの場合小数点があるが、指数が指定されている場合は省略できる。例えば、2e3は値2000の浮動小数点リテラルである。

小数点の前の値は、0の場合は省略できる。例えば、.25は値"quarter"を持つリテラルだ。

オプションの_文字は浮動小数点リテラルとも組み合わせて使用できる。例えば、1_000.5のように。

浮動小数点リテラルの型

明示的に指定しない限り、浮動小数点リテラルの型はdoubleだ。fおよびF指定子はfloatを意味し、L指定子はrealを意味する。例えば、1.2double3.4ffloat5.6Lrealだ。

文字リテラル

文字リテラルは、シングルクォートで囲んで指定する。例:'a''\n''\x21'など。

文字自体として:文字は、キーボードから直接入力するか、別のテキストからコピーして入力することができる:'a'、'ş'など。

文字指定子として:文字リテラルは、バックスラッシュ文字とそれに続く特殊文字で指定することができる。例えば、バックスラッシュ文字自体は、'\\'で指定することができる。以下の文字指定子が使用できる。

 構文 定義
\'シングルクォート
\"ダブルクォート
\?疑問符
\\バックスラッシュ
\aアラート(一部の端末ではベル音)
\b削除文字
\f改ページ
\n改行
\rキャリッジリターン
\tタブ
\v垂直タブ

拡張ASCII文字コードとして:文字リテラルは、そのコードで指定することもできる。コードは、16進数または8進数で指定できる。16進数を使用する場合、リテラルは\xで始まり、コードには2桁の数字を使用しなければならない。8進数を使用する場合、リテラルは\で始まり、3桁までの数字を使用しなければならない。例えば、リテラル'\x21''\41'はどちらも感嘆符だ。

Unicode文字コードとして:リテラルがuに4桁の16進数が続く形で指定されている場合、その型はwcharになる。Uに8桁の16進数が続く形で指定されている場合、その型はdcharになる。例えば、'\u011e''\U0000011e'はどちらもĞ文字で、それぞれ型はwchardcharになる。

名前付き文字エンティティとして:エンティティ名を持つ文字は、HTML文字エンティティ構文を使用してその名前で指定することができる。 '\&name;'。Dは、HTML5のすべての文字エンティティをサポートしている。例えば、'\€'は €、'\♥'は ♥、'\©'は©となる。

文字列リテラル

文字列リテラルは文字リテラルの組み合わせであり、さまざまな方法で指定できる。

ダブルクォートで囲まれた文字列リテラル

文字列リテラルを指定する最も一般的な方法は、"hello"のように、文字を二重引用符で囲むことだ。文字列リテラルの個々の文字は、文字リテラルの規則に従う。例えば、リテラル"A4 ka\u011fıt: 3\½TL""A4 kağıt: 3½TL"と同じだ。

Wysiwyg 文字列リテラル

文字列リテラルをバッククォートで指定した場合、文字列を構成する個々の文字は、文字リテラルの特別な構文規則に従わない。例えば、リテラル `c:\nurten`は、Windowsオペレーティングシステムではディレクトリ名になる。これを二重引用符で記述した場合、'\n'改行文字を意味する。

writeln(`c:\nurten`);
writeln("c:\nurten");
D
c:\nurten  ← wysiwyg (見たままがそのまま表示される)
c:         ← 文字リテラルは改行として扱われる
urten

Wysiwyg文字列リテラルは、ダブルクォートで指定する代わりに、r文字を先頭に付けることで指定することもできる。r"c:\nurten"もWysiwyg文字列リテラルだ。

区切り文字付き文字列リテラル

文字列リテラルには、二重引用符の間に直接入力した区切り文字を含めることができる。これらの区切り文字は、リテラルの値の一部とはみなされない。区切り文字付き文字列リテラルは、開二重引用符の前にqで始まる。例えば、q".hello."の値は "hello" だ。ドットは値の一部ではない。改行で終わる限り、区切り文字は1文字以上でもかまわない。

writeln(q"MY_DELIMITER
first line
second line
MY_DELIMITER");
D

MY_DELIMITERは値の一部ではない。

最初の行
2番目の行

このようなインデントを含む複数行の文字列リテラルは、ヘリドックと呼ばれる。

トークン文字列リテラル

qで始まり、{}を区切り文字として使用する文字列リテラルは、合法的なDソースコードのみを含むことができる:

auto str = q{int number = 42; ++number;};
writeln(str);
D

出力:

int number = 42; ++number;
D

この機能は、テキストエディタが文字列の内容を構文強調表示されたDコードとして表示するのに特に役立つ。

文字列リテラルの型

デフォルトでは、文字列リテラルの型はimmutable(char)[]である。cw、またはd文字を付加すると、文字列の型がそれぞれimmutable(char)[]immutable(wchar)[]、またはimmutable(dchar)[]として明示的に指定される。例えば、"hello"dの文字はimmutable(dchar)型である。

文字列の章で、これら3つの文字列型は、それぞれstringwstringdstringという別名があることを見た。

リテラルはコンパイル時に計算される

リテラルは式として指定することができる。例えば、1月の合計秒数を2678400または2_678_400と書く代わりに、その値を構成する項、つまり60 * 60 * 24 * 31で指定することができる。この式内の乗算演算は、プログラムの実行速度に影響を与えない。プログラムは、2678400と記述した場合と同じようにコンパイルされる。

文字列リテラルについても同様だ。例えば、"hello " ~ "world"の連結演算は、実行時ではなくコンパイル時に実行される。プログラムは、単一の文字列リテラル"hello world"が含まれているかのようにコンパイルされる。

演習
  1. 次の行はコンパイルエラーを引き起こす:
    int amount = 10_000_000_000;    // ← コンパイルエラー
    D

    この行がコンパイル可能になり、amountが100億になるようにプログラムを変更しよう。

  2. 変数の値を増加させ、それを連続して出力するプログラムを書いてみよう。値は常に同じ行に出力し、前の値を上書きするようにしよう。
    番号: 25774  ← 常に同じ行に

    '\n'以外の特殊文字リテラルが役立つかもしれない。