やさしいD言語クイズ

# はじめに

昨年のアドベントカレンダーにあった[Goクイズ](https://qiita.com/advent-calendar/2020/goquiz)が正直うらやましく思い、D言語クイズを考えてみました。

D言語を知らない方でも、ソースコードは何となく読める程度の内容なので、これを機会にD言語に興味を持っていただけると幸いです。

# クイズの前提
[Online D Editor](https://run.dlang.io/)（2021/12/14現在）での実行結果をクイズの正解とさせていただきます。

## Online D Editorの環境情報（2021/12/14現在）

```d:
import std;
void main()
{
    writeln(__VENDOR__);
    writeln(__VERSION__);
    version(BigEndian)
    {
        writeln("Big endian byte order ");
    }
    else version(LittleEndian)
    {
        writeln("Little endian byte order");
    }
}
```
```text:実行結果
Digital Mars D
2098
Little endian byte order
```

:::note info
ここから問題です。
:::

# 問題１
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void func1()
{
    scope(exit) write("1");
    write("2");
    throw new Exception("");
}
void main()
{
    scope(exit) write("3");
    scope(exit) write("4");
    write("5");
    try
    {
        func1();
    }
    catch (Exception e)
    {
    }
    write("6");
}
```

# 問題２
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void main()
{
    ubyte[] a = [ 0x12, 0x34, 0x56, 0x78 ];
    uint[]  b = a.to!(uint[]);
    writefln("%(%02x %)", cast(uint[])a);
    writefln("%(%02x %)", cast(ubyte[])b);
}
```

# 問題３
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

```d:
import std;
void func1()
{
    write(x);
}
int x = 5;
void main()
{
    void func1()
    {
        write(x+3);
    }
    int x = 4;
    write(x);
    write(.x);
    func1();
    .func1();
}
```

# 番外編
答えが一意に決まらないだろうとの理由で、正式な問題ではなく、番外編としました。
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。
あえて`destroy(c)`はコメントアウトしています。

```d:
import std;
class C1 {
    this(){  write("1"); }
    ~this(){ write("2"); }
    static this(){  write("3"); }
    static ~this(){ write("4"); }
}
class C2 : C1 {
    this(){  write("5"); }
    ~this(){ write("6"); }
    static this(){  write("7"); }
    static ~this(){ write("8"); }
}
void main()
{
    C2 c = new C2();
    write("9");
//    destroy(c);
}
```

:::note warn
ここから回答編です。ネタばれ注意！！
:::

# 問題１の答え

<details><summary>問題１の実行結果</summary><div>

```text:問題１の実行結果
521643
```
</div></details>

答えの補足

* `scope(exit)`は、スコープから抜けるタイミングで実行されます。（3, 4は5, 6よりあとに出力されます）
* `scope(exit)`は、例外(`exception`)が発生しても、呼び出されます。（1が出力されるのは仕様です）
* `scope(exit)`が複数呼び出された場合は、呼び出し順の逆から実行されます。（4→3の順で出力されるのは仕様です）

https://dlang.org/spec/statement.html#scope-guard-statement

# 問題２の答え

<details><summary>問題２の実行結果</summary><div>

```text:問題２の実行結果
78563412
12 00 00 00 34 00 00 00 56 00 00 00 78 00 00 00
```
</div></details>

答えの補足

* `to`は、実際にデータの変換を行います。元データとは別にデータが生成されます。
* キャスト(`cast`)は、データ変換を行いません。元データを別の型とみなしているだけです。
* `writefln`を使えば、配列の16進数表示も簡潔に書けます。

https://dlang.org/spec/expression.html#cast_expressions

# 問題３の答え

<details><summary>問題３の実行結果</summary><div>

```text:問題３の実行結果
4585
```
</div></details>

答えの補足

* グローバルとローカルに同じ名前の変数や関数を宣言できます。
* グローバル側にアクセスしたい場合は、変数名や関数名の前に`.`をつけます。
* `main`関数内の`func1`が参照する`x`はグローバル側になります。もし、`main`関数内の`func1`よりも先に`int x = 4;`が宣言されていれば、ローカル側の`x`が参照され、問題３の答えは`4575`となっていました。


# 番外編の答え

<details><summary>番外編の実行結果</summary><div>

```text:番外編の実行結果
371598462
```
</div></details>

[Online D Editor](https://run.dlang.io/)（2021/12/14現在）での実行結果を正解とさせていただきます。

答えの補足

* `static this`は、`main`より先に呼び出されます。
* クラスに継承関係がある場合、`static this`も、`this`も基底クラスが先に呼び出されます。
* クラスに継承関係がある場合、`static ~this`も、`~this`も派生クラスが先に呼び出されます。
* `static ~this`は対象スレッドの終了時に、`~this`はオブジェクト削除のタイミングに呼び出されます。どちらが先に実行されるかの規定はなく、この場合、GC(オブジェクト削除)が最後に実行されたということです。
* ちなみに、`destroy`を呼び出せば、`~this`がすぐに実行されます。

https://dlang.org/spec/class.html#constructors

# 最後に

普段からD言語を使っている方には、簡単すぎたかもしれません。
問題作成のために、言語仕様をじっくり読んだので、私自身勉強になりました。
第２弾も予定していますので、よろしくお願いします。