令和のD言語基礎文法最速マスター

# はじめに

令和2年、D言語版の基礎文法最速マスターです。

よく見る文法や記述をサクッと紹介していきます。
これを見ていただければ少なからず言語としての雰囲気が分かっていただけると思います。

過去に @repeatedly さんが大体書かれているので、少し令和風に追記・編集する形でやっていきます。

- D言語基礎文法最速マスター (Thanks @repeatedly!）
    - https://gist.github.com/repeatedly/2470712

動かしながら網羅的に学びたい方は以下D言語ツアーを、正規表現などもう少し実用的な書き方を知りたい方はD言語Cookbookもご覧ください。

- D言語ツアー
    - https://tour.dlang.org/tour/ja/welcome/welcome-to-d
- D言語Cookbook
    - https://dlang-jp.github.io/Cookbook/

~~正直D言語ツアーで十分な気もしますが~~頑張ってやっていきます。

# 1. 基礎

## ビルドツール `DUB`

### プロジェクト準備

`dub` というビルドツールがあり、多くの場合はこれを使えばソースファイルなどが作られてプログラムを書く準備が整います。
細かく色々やりたい場合はコンパイラを直接使うこともできます。

こちらOSのパッケージマネージャーや[公式サイト](https://dlang.org/download.html)からダウンロードでき、LinuxでもWindowsでもMacでも同じコマンドになっています。

```console
mkdir app
cd app
dub init
```

```:ファイル構成
app
    source
        app.d
    dub.json
```

### ビルド・実行

実行ファイルの作成や実行もコマンド1つで簡単です。

```console:ビルド（実行ファイルの生成）
dub build
```

```console:ビルド＋実行
dub run
```

## ソースファイル

文字コードはUTF-8で記述します。ファイルの拡張子は `.d` です。

## main

D言語は用意した `main` という関数から実行されます。エントリポイントと呼ばれます。
処理のまとまりを `{}` で区切るスタイルで、C言語やJava、C#などと同様になっています。

```d:app.d
void main() { }
void main(string[] args) { }
```

C言語では必要だった戻り値が省略できます。記述することもできます。

```d:app.d
int main() { }
int main(string[] args) { }
```

## import文

`import` 文を使って各種ライブラリを読み込みます。

たとえばコンソール画面に文字を出力するには、標準ライブラリの `std.stdio` を読み込んで使います。
これによって `write` や `writeln`、 `writef` や `writefln` といった関数が使えるようになります。

```d
import std.stdio;    // 読み込み

void main() {
    write(1);            // 改行なし
    writeln(1);          // 改行あり
    writef("%02d", 1);   // フォーマット指定改行なし
    writefln("%02d", 1); // フォーマット指定改行あり
}
```

特定のシンボル（定義）のみをインポートすることもできます。これは選択インポートと呼ばれます。

```d:
import std.stdio : writeln;

writeln("Hello");
write("Hello");   // 利用できない
```

## 変数の宣言

D言語では `型 変数名;` というように宣言します。

```d
int a;  // デフォルト値で初期化されます。intなら0です。
```

また、初期化に使った値から型を推論して省略するための `auto` という予約語があります。

```d
auto a = "auto";   // aはstring型
```

他の修飾子がある場合も型推論が効きます。

```d
const a = "hoge"; // const(string)型
```


## コメント

主に3種類あります。

```d
// 一行コメント

/*
   複数行コメント
 */

/+ /+
   ネスト可能複数行コメント
 +/ +/
```

これに定義の説明文などを書き、ドキュメント生成したりツールチップで表示されるよう拡張した「DDocコメント」と呼ばれるバージョンがあります。

記述ではMarkdown構文も利用できます。
また複数行コメントは形式的に毎行 `*` や `+` を付けて見やすくデコレーションする文化があります。

```d:
/// 1行で関数の説明を書くDDocコメント

/**
 * 複数行で説明を書くDDocコメント
 *
 * Params:
 *     x = 引数の説明など、他にも細かい記述が可能
 */

/++
 + 複数行コメントと同様のネスト可能バージョン
 +/
```


# 2. データ型

## 数値

整数と浮動小数点数があります。
C言語とは異なり、すべてサイズ固定です。

整数は4種、頭にuがつくと符号なしになります。

```d
byte   n1; // 1byte 符号あり
ubyte  n2; // 1byte 符号なし
short  n3; // 2byte 符号あり
ushort n4; // 2byte 符号なし
int    n5; // 4byte 符号あり
uint   n6; // 4byte 符号なし
long   n7; // 8byte 符号あり
ulong  n8; // 8byte 符号なし
```

浮動小数点数は3種です。基本は `double` で、 `float` にするには末尾に `f` を付けます。

```d
float  num1 = 1.234f; // fを付けるとfloat
double num2 = 1.234;
real   num3 = 5.678;  // ハードウェアがサポートする最大精度(x86 CPUなら80bit)
```

ちなみに複素数型もありますが非推奨です。標準ライブラリの `std.complex` を利用します。


### 四則演算

よくある記号のパターンで、 `+` `-` `*` `/` の4つを使います。

```d
int num; // 整数型
num = 1 + 1;
num = 1 - 1;
num = 1 * 2;
num = 5 / 2;  // 2
num = 5 % 2;  // 1
```

演算子のどちらかが浮動小数点数の場合、結果も浮動小数点数になります。

```d
double num = 5.0 / 2;  // 2.5(numがintなどの整数型だとコンパイルエラー)
```

### インクリメントとデクリメント

前置も後置もサポートされています。
「数値的に1を足す/引く」という論理的な意味が規定されています。ポインタを進めるような用途では利用されません。

```d
i++;
++i;

--i;
i--;
```
 
## 真偽値

真と偽の2値を表す専用の `bool` 型が存在します。
真が `true` で偽が `false` です。

```d:
bool flag = true;
flag = false;
```

## 定数（enum）

定数を表す `enum` があります。

```d:
enum StringTypes {
    UTF8,
    UTF16,
    UTF32,
}

auto t = StringTypes.UTF8;
```

## 文字列

文字列は基本UTF-8型で `string` 型が用意されており、ダブルクォートで囲んで構築します。
文字単体では `char` 型です。

ダブルクォートの中では、バックスラッシュを使ったエスケープシーケンスで `\t` (タブ)や `\n` (改行)などの特殊文字を利用することができます。

```d
string str1 = "abc";
string str2 = "a\tbc\n";

char c = str1[0];
```

これにUTF-16用の `wchar` ベースで `wstring`、UTF-32用の `dchar` ベースで `dstring` と3種あり、それぞれ接尾語をつけることでリテラルの型を明示的に指定できます。

```d
string str3 = "hello"c  // 各文字はchar型
wstring str4 = "hello"w  // 各文字はwchar型
dstring str5 = "hello"d  // 各文字はdchar型
```

なお、D言語での文字列は、後述する配列の一種に過ぎません(`string` は `immutable(char)[]` と同じ)。
これは「変更できないUTF-8型の文字を要素に持つ動的配列（スライス）」という意味です。

### 文字列操作

```d
// 結合
auto str = "aaa" ~ "bbb";

// 長さ(バイト)
auto length = "abcdef".length;

// 切り出し
auto substr = "abcd"[0..2];  // "ab"

/* これ以降のものはstd.stringが必要です */
import std.string;

// 分割
auto record = "aaa,bbb,ccc".split(",");  // ["aaa", "bbb", "ccc"]

// 検索
auto idx = "abcd".indexOf("bc");  // 見つかった場合はその位置、見つからなかった場合は-1
```

## 配列（動的配列）

配列の型は要素型の後ろに `[]` を付けて宣言します。
初期化は `[要素, 要素]` と `[]` の中にカンマ区切りで記述します。

```d:
int[] arr = [100, 200, 300];
string[] urls = ["https://dlang.org", "https://github.com/"];
```

C言語とよく比較されますが、`[]` が型のほうについているのが違いです。
変数宣言は一貫して `型 変数名;` という形式で読めるようになっています。


### 要素の参照と代入

```d
int[] a = [10, 20];

// 参照
a = arr[0];  // 10
b = arr[1];  // 20
c = arr[5];  // Error! 要素数より多いと例外が投げられる

// 代入
arr[0] = 1;
arr[1] = 2;
arr[5] = 5;  // 参照と同じくエラー
```

### 要素の個数

```d
size_t len = arr.length; // size_t は 32bit環境ならuint、64bit環境ならulongです

// 要素を増やす(増えた分はデフォルト値で埋められます)
arr.length += 10;
```

### 配列のスライス

配列の一部領域を取り出したり、まとめて値を設定したりできます。

```d:
int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

int[] r = arr[2 .. 5]; // [2, 3, 4]

arr[6 .. 8] = 10; // [0, 1, 2, 3, 4, 5, 10, 10, 8, 9]
```

全体のスライス、ある場所から最後まで、といった操作に対して簡単な記法がサポートされています。

```d:
arr[] = 100; // 全要素を 100 に設定
arr[5 .. $] = 200; // インデックスで5から最後までを 200 に設定
```

スライス同士の代入なども可能です。

```d:
arr[0 .. 100] = arr2[100 .. 200]; // あるスライスを別のスライスに代入可能
```

### ベクトル演算

スライスの応用で、配列の一部に対するベクトル演算が可能です。ループも必要なくなるかもしれません。
ちなみにベクトル演算とは、CPUの特殊な命令(AVX2など)を用いて複数要素の計算をまとめて行うことで高速化を図るものです。

```d
auto a = [1, 2, 3];
a[] += 10;  // [11, 12, 13]
```

### 配列の操作

`std.array` を使うとD言語での標準的なインターフェイス(Range)が利用できます。

```d
import std.array;

auto arr = [1, 2, 3];

// 先頭を取得
auto a = arr.front;  // aは1

// 先頭を削除
arr.popFront();  // arrは[2, 3]

// 先頭に追加(push系がないのでinsertで)
arr.insert(0, 5);  // arrは[5, 2, 3]

// 末尾を取得
auto b = arr.back;  // bは3

// 末尾を削除
arr.popBack();  // arrは[5, 2]

// 末尾に追加
arr ~= 9;  // arrは[5, 2, 9]
```

## 連想配列

連想配列も `[]` を使います。
連想配列の型は、 `要素型[キー型]` という形式で宣言します。
初期化は `[]` の中でキーと値を `:` で区切ります。

```d
int[string] hash = ["a" : 1, "b" : 2];
```

### 要素の参照と代入

```d
// 参照
hash["a"]  // 1
hash["b"]  // 2
hash["z"]  // 配列と同じく例外が投げられる

// 代入
hash["c"] = 5
hash["d"] = 7
```

### 連想配列の操作

```d
// キーの取得
auto hashKeys = hash.keys;  // ["a", "b", "c", "d"]

// 値の取得
auto hashValues = hash.values; // [1, 2, 5, 7]

// キーの存在確認
auto val = "a" in hash;  // valには1へのポインタ、なければnull

// ハッシュのペアの削除
hash.remove("a");
```

値がなければデフォルト値、といった記述には `require` 関数を使います。

```d:
int[string] settings;

auto timeout = settings.require("timeout", 120);
```

# 3. 制御文

## if文

```d
if (cond) {
    // do something
}
```

## if ～ else文

```d
if (cond) {
    // do something
} else {
    // do something
}
```

## if ～ else if 文

```d
if (cond) {
    // do something
} else if (cond) {
    // do something
}
```

## switch文

Cとは違い、文字列が使えたり `case` を並べて書くことが出来ます。

```d
switch (command) {
  case "foo", "bar":
    // do something
    break;
  case "baz":
    // do something
    break;
  default:
}
```

これを拡張した `final switch` という構文もあります。
これは主に `enum` を対象としたもので、すべての分岐を網羅的に書かないとコンパイルエラーになるというものです。

```d:
enum Types {
    A,
    B,
}

Types t;
final switch (t) {
    case Types.A:
        writeln("A");
    // Bの分岐がないためエラー
}
```


## while文

```d
uint i;
while (i < 5) {
    // do something
    ++i;
}
```

## for文

```d
for (size_t i = 0; i < 5; i++) {
    // do something
}
```

## foreach文

配列などの要素を処理するため、効率よく記述できるようにしたものです。
配列や連想配列、`opApply` を実装していたり `Range` の機能を満たすオブジェクトが処理対象となります。

```d:配列やRange
foreach (elem; arr) {
    // do something
}
```

インデックスがほしいときも変数を増やすだけです。

```d:配列インデックスあり
foreach (i, elem; arr) {
    // do something
}
```

連想配列も同様です。

```d:連想配列
int[string] dic;

foreach (key, value; dic) {
}
```

要素を弄りたい場合は `ref` をつけます。

```d:要素の書き換え
foreach (ref elem; arr) {
    // do something
    elem += 10;
}
```

数値的に区間を定めることもできます。
開始と終了のインデックスは一度しか評価されないことが保証されています。

```d:
foreach (i; 0 .. 100) {
    // do something
}
```

## with文

要素へのアクセスを簡略化する `with` 文があります。VB.NETと同じような機能です。

```d:
struct S {
    int value;
}

S s;
auto a = s.value;

with (s) {
    auto x = value; // 単なる value が見つからない場合、 s.value と同じ意味になる
}
```

いろいろな記述を省略できるようにするためのものなので、`final switch` 構文で各 `case` における `enum` へのアクセスを省略するような書き方で使われることが多いです。

```d:
enum Types {
    A,
    B,
}

Types t;
final switch (t) with (Types) {
    case A:
        writeln("A");
        break;
    case B:
        writeln("B");
        break;
}
```


## スコープガード文

処理のブロックを抜けるときの処理をブロックの途中に書くことができる機能です。
使い終わったら破棄が必要なオブジェクトに対し、初期化とセットで破棄を書いて破棄忘れを予防するような機能です。

`scope (条件) 処理` といった記述になります。

```d:
auto f = new Resource();
scope (exit) f.dispose();

// do something
```

他であまり見られない機能としては、「抜けるときに必ず」「成功」「失敗」で3種の書き分けができることです。
処理が失敗したときだけロールバックしたり通知する、といった処理も簡単に書くことができます。

```d:
auto res = new Resource();
scope (exit) {
    res.dispose();
    writeln("必ず実行");
}
scope (success) writeln("成功時のみ");
scope (failure) writeln("失敗時のみ");
```

## Synchronized文

マルチスレッドの同期を簡単に行う `synchronized` 文が組み込まれています。
これによって1つのスレッドしか実行できない範囲を明示することができます。
`Mutex` で同期のコンテキストを指定することもできます。

```d:
ulong count = 0;
Thread[] threads;
foreach (i; 0 .. 1000) {
    auto t = new Thread({
        synchronized {
            count++;
        }
    });
    threads ~= t;
}
// do something
```


# 4. 関数/デリゲート

## 関数

関数はC言語と同じように記述します。
`戻り値 関数名(引数一覧) { }` という形式です。

```d:
int square(int n) {
    return n * n;
}
```

D言語ではこれに色々と追加の指定があります。
たとえば引数に `in` を付けると入力を表し書き換え不可、 `ref` は参照として書き換え可能、他にも遅延評価（使うときまで計算されない）のための `lazy` などがあります。

```d
void foo(in int x, ref int y, lazy int z) { }
```

関数の処理内容に対して制約掛けるための属性も多数あります。
例外（Exception）を投げない `nothrow`、 安全とマークされた関数しか実行しない `@safe`、グローバル変数などの副作用がない `pure`、GCが動作しないことを示す `@nogc` などです。

```d:
void foo() nothrow pure @safe @nogc { }

// まとめて指定する範囲指定の構文やブロック構文もあります
nothrow:

void hoge() {} // nothrow

@nogc {
    void fuga() {}      // nothrow @nogc
    void hage() pure {} // nothrow pure @nogc
}
```

### デリゲート

デリゲートはネストされた関数などのことです。
クロージャと呼ばれる動的に作られた関数オブジェクトもデリゲート型の一種となります。

```d
uint delegate() counter; // 引数なし、戻り値がuintのデリゲート

// デリゲートを返すネストされた関数
uint delegate() createCounter()
{
  uint count;
  return { return ++count; };  // {}はdelegateリテラル(引数がないので()は省略)
}

counter = createCounter();
writeln(counter());  // 1
writeln(counter());  // 2
```

以下のようなラムダシンタックスもあります。

```d
void f(uint delegate(uint) d)
{
    writeln(d(10));
}

void main()
{
    f((x) { return x + 2; }); // 12
    f(x => x + 2);            // ラムダシンタックス(上と等価)
}
```

# 5. 知っておいた方がよい文法・高度な機能

## 標準出力

標準入出力は `std.stdio` というモジュールにあり、 `write` や `writeln` といった便利な関数が提供されます。

これを使うと文字列以外にも数値や配列を含む引数の出力が簡単に行えます。
特に `writeln` は様々な用途で見かけるもので非常に便利に使うことができます。

- `write`
    - 引数をそのまま出力
- `writeln`
    - 引数を出力後、最後に改行コードを出力
- `writef`
    - 引数を書式化文字列に従って出力
- `writefln`
    - 引数を書式化文字列に従って出力後、最後に改行コードを出力

```d:
import std.stdio;

void main() {
    // Hello, world!\n
    write("Hello, ");
    writeln("world!");

    // [10, 20, 30]
    int[] arr = [10, 20, 30];
    writeln(arr);
}
```

書式化文字列に使える構文はC言語に近い構成になっています。

```d:
// -----
// 10, 20, 30
// -----
writef("-----\n%d, %d, %d\n-----", 10, 20, 30);

// test: 100
writefln("test: %d", 100);
```

また、書式化文字列はテンプレート引数として渡すことにより引数の型と一致をチェックしたり、実行時の解析コストをなくすこともできます。

```d:
// コンパイル時に引数チェックと書式化文字列の解析を行う
writefln!"-----\n%d, %d, %d\n-----"(10, 20, 30);
```

## インターフェース

JavaやC#と同様の機能を提供しています。
後述のクラスに対して実装すべき関数などを制約として定義するものです。

```d:
interface MyIntRange {
    bool empty() const;
    int front() const;
    void popFront();
}
```

なお `final` という属性を付けることで、クラス側に書かなくてもインターフェースで固定された実装を持たせることができるようになっています。

```d:
interface MyMessage {
    final void print() {
        writeln("MyMessage.print");
    }
}
```

## クラス

JavaやC#と同様の機能を提供しています。

```d
class Person
{
private:  // 以降はprivate
    string name_;

public:  // 以降はpublic
    @property
    {
        // @properyをつけるとname()ではなくnameで呼び出せるようになる
        // p.name
        string name() const { return name_; }
        // p.name = newName
        void name(string name) { name_ = name; }
    }

    this(string name)  // コンストラクタはthis
    {
        name_ = name;
    }

    ...
}  // Cなどと違い;はいらない
```

その他にも `interface`、PODとして扱える `struct` や `union`、演算子オーバーロードなどもあります。
また、D言語はGCを使ってメモリ管理しているため、`new` した後 `delete` する必要はありません(自ら `malloc` などした場合は勿論 `free` が必要です)。

## テンプレート

C++と同じようなテンプレート機能を提供しています。
これは特定の宣言のうち、一部の型などを入れ替えて使う汎用的な定義であり、文字通り「テンプレート」として動作します。

`static if` といったコンパイル時計算の分岐もあり、C++よりも幾分すっきり書けるようになってます。以下は階乗を計算するテンプレートです。

```d
template factorial(int n)
{
  static if (n == 1)
    enum factorial = 1;
  else
    enum factorial = n * factorial!(n - 1);
}

/* C++などとは違い<>を使わず!()を使う */
factorial!(5) // 120
```

この `static if` は通常の `if` と違ってスコープを生成しないため、変数宣言の切り替えなどが非常にやりやすくなっています。
クラスや関数(UFCSの項参照)でも使えます。

```d
class Hoge(T)
{
    static if (is(T == long)) {
        int value;
    } else {
        T value;
    }
}
```

### テンプレートミックスイン

単一継承のD言語では、クラス間で実装を共有する時にテンプレートを使います。

```d
mixin template HogeImpl()
{
    uint hoge_;
    uint hogeTwice() { return hoge_ * hoge_; }
}

class A
{
    mixin HogeImpl;  // Aで定義したかのように使える
}

class B
{
    mixin HogeImpl;  // 同様
}
```

## UFCS (Uniform Function Call Syntax)

クラスなどのメソッド呼び出しのように第一引数を外に出して使えるシンタックスシュガーです。

```d
void foo(T)(T obj) {}

// 本来はfoo([1, 2, 3])とか
[1, 2, 3].foo();
5.foo();
2.5f.foo();
```

`std.array` や `std.string` で定義された関数が `var.method()` のように呼べたのはこの機能のおかげです。

## 例外処理

一般によく知られている `Exception` クラスを使った例外機構があります。
構文的には、 `throw` および `try` - `catch` - `finally` が利用できます。


```d:
void foo() {
    throw new Exception("エラー");
}

try {
    foo();
}
catch (Exception e) {
    writeln(e.msg); // エラー
}
finally {
    writeln("終了");
}
```

## Range

D言語の標準ライブラリは今このコンセプトを中心に開発されており、核となる `std.range` に満たすべきインターフェイスが定義されています。
以下は `std.range` ベースのアルゴリズムの例です。

```d
import std.algorithm;

auto arr = [1, 2, 3, 4, 5];

// 条件に合うものだけを選ぶ
filter!("a % 2 == 0")(arr);  // [2, 4]
// '"a % 2 == 0"'の代わりに'a => a % 2 == 0'でもOK、delegateと文字列両方受け付ける
filter!(a => a % 2 == 0)(arr);  // [2, 4]

// 条件に合うものを除く
remove!("a % 2 == 0")(arr);  // [1, 3, 5]

// 加工結果をRangeで返す
map!("a * a")(arr);  // [1, 4, 9, 16, 25]

// 降順にソートする
sort!("a > b")(arr);  // [5, 4, 3, 2, 1]
```

基本的に、これらのアルゴリズムが返すのは `arr` の型ではなく、それぞれの計算を隠蔽した `Range` オブジェクトです。これによって、`Range` は基本的には計算を遅延し、それぞれの `Range` をつなげてもなるべく中間オブジェクトを作らないように工夫されています。
配列として結果を返して欲しい時は `std.array` の `array` 関数を使います。

```d
import std.array;

array(map!("a * a")(arr));
```

これらはUFCSを使うと、以下のように処理の流れ通り気持ちよく記述することができます。

```d:
// 連続した操作もすっきり
arr.filter!("a % 2 == 0").map!("a * a").array();
```


## 型変換

数値を文字列にしたり、逆に文字列を数値に変換するなど、型変換を簡単に行うために `to` という汎用テンプレート関数があります。

```d:
import std.conv;

int num = 100;
auto str = to!string(num);
auto num2 = to!int(str);
```

UFCSの機能を使うと変換を後置できるので、処理の流れを綺麗に書くこともできます。

```d:
auto str = num.to!string();
auto num2 = str.to!string();
```

## 単体テスト

`unittest` というキーワードで囲った所に単体テストをかけます。
満たすべき条件は `assert` という式で書くことができます。

大体どこにでも書けるのが特徴で、クラス内など宣言の近くに書くのがD言語の作法です。

```d
unittest 
{
    bool foo() { /* do something */ return flag; }
    assert(foo());
}
```

この単体テストは `dub` コマンドを使うと、 `dub test` という形式で実行することができます。

またDDoc形式のドキュメントコメントをHTMLなどに出力する際、直前の定義のサンプルとして使うこともできます。
関数とセットにすると以下のようになります。

```d:
/// 引数を二乗します
double square(double x) {
    return x * x;
}

/// ditto
unittest {
    assert(square(1.0) == 1.0);
}
```

ちなみに `ditto` というのは「同上」という意味の特別なワードです。

## 契約

関数の入力や出力が満たすべき条件を記述することができ、関数の責務を明示することができます。
それぞれ「事前条件」と「事後条件」と呼ばれ、 `in` と `out` というキーワードで条件を描くことにより定義します。
またリリースモードでは処理が取り除かれるのでパフォーマンスには影響しません。

```d:
double sqrt(double x)
in (x >= 0)                        // 入力に負数は禁止
out (result; result * result == x) // 戻り値は2回掛けると元に戻る
do {
    // do something
}
```

構造体やクラスに向けて、必ず満たしているべき条件を書く「不変条件」というのもあります。
キーワードとしては `invariant` というものです。

これはクラスが2つの配列を持っていて、それらが必ず同じ長さでないといけない場合などに使います。
たとえば以下の例だと、`arr1` だけ設定するとその時点で長さがずれてエラーになるため、必ず `setArrays` を呼ぶことを強制できます。

```d:
class SomeArrays {
    int[] arr1;
    double[] arr2;

    void setArrays(int[] arr1, double[] arr2) {
        this.arr1 = arr1;
        this.arr2 = arr2;
    }

    invariant {
        assert(arr1.length == arr2.length); // 必ず満たすべき条件
    }
}
```

## CTFE(Compile Time Function Excecute)

D言語ではコンパイル時に色々な処理をすることが出来ます。
コンパイル時にメモリの確保やクラスの生成も出来ますし、例外も投げれますし、もちろん数値計算や配列も操作出来ます。

そのため、コンパイル時に定数を渡せばそれなりに色々な関数が動作します。
たとえば、以下のような乱数生成も普通にコンパイル時に動きます。（シードは0固定ですが）

`enum` で宣言した変数に対し、初期化に使う式がコンパイル時計算の対象となります。

```d
ulong gen()
{
    Random r;
    popFrontN(r, 1000);
    return r.front;
}

enum num = gen(); // gen()がコンパイル時に計算されて結果だけが保持される
```


# 終わりに

まだまだ書けてない機能は多数ありますが、よく見る主要な機能や魅力的な部分は大体書けたかと思います。
メタプログラミング関連の機能が強く、CやJavaに似た構成であり学習曲線が低いのが特徴です。
コンパイルや実行も高速で様々な分野で利用されています。

Qiitaにもいろいろ記事がありますが、わからないことがあればTwitterで #dlang をつけてつぶやくと大体誰かが答えてくれるのでぜひ聞いてみてください。