読者です 読者をやめる 読者になる 読者になる

【D言語】Voldemort Typeについて【名前を呼んではいけないあの型】

D言語

D言語erのみなさん、あけましておめでとうございます。

今回は、ニュースグループでよく目にするけれど、日本語の資料は全くないVoldemort Typeについて、語っていきます。 大丈夫です、ハリー・ポッターのヴォルデモートであってます。


例えば、動的配列からInputRangeを作成する関数を作ってみます。


import std.stdio;

struct ArrayToInputRange(E)
{
    E[] array;
    
    this(E[] array)
    {
        this.array = array;
    }

    @property
    E front()
    {
        return array[0];
    }

    void popFront()
    {
        array = array[1..$];
    }

    @property
    bool empty()
    {
        return array.length == 0;
    }
}

auto toInputRange(E)(E[] array)
{
    return ArrayToInputRange!E(array);
}

void main()
{
    auto range = [1, 2, 3, 4].toInputRange();
    range.writeln(); // [1, 2, 3, 4]
}

できました。簡単ですね。 簡単なのですが、一つ問題があります。それは、

Rangeを作るためだけに作ったArrayToInputRangeが、いろんな場所から見えちゃう!!

という点です。


上のソースコードのmain関数の中身を見てみてください。 ArrayToInputRangeなんてどこにも出てきてませんね。 D言語にはautoがあるので、わざわざArrayToInputRange!intなんて書く必要がありません。

toInputRange以外ではArrayToInputRangeは使われるはずがありません。 それにも関わらず、ArrayToInputRangeは存在してしまうので、名前空間を汚していきます。 つまり、カプセル化に失敗しているのです。

確かに、モジュールが違えば、privateで隠すことができます。 が、同じモジュール内では、privateは効果を発揮しないので、完全にカプセル化できません。


さて、こんな感じに書いてみたらどうでしょう?


import std.stdio;

auto toInputRange(E)(E[] array)
{
    struct ArrayToInputRange
    {
        E[] array;

        this(E[] array)
        {
            this.array = array;
        }

        @property
        E front()
        {
            return array[0];
        }

        void popFront()
        {
            array = array[1..$];
        }

        @property
        bool empty()
        {
            return array.length == 0;
        }
    }
    return ArrayToInputRange(array);
}

void main()
{
    // toInputRange.ArrayToInputRange <ー これは出来ない!!
    auto range = [1, 2, 3, 4].toInputRange();
    range.writeln(); // [1, 2, 3, 4]
}

なにか興味深いことが起きていますね!! ArrayToInputRangeがtoInputRangeのスコープ内に移動したおかげで、toInputRangeの外からは、その名前を呼べなくなっています。 名前を呼ぶことができない・・・そう、これこそがVoldemort Typeです。

上のコードは、ArrayToInputRangeをVoldemort Typeにした(つまりスコープを関数内に移した)ことによって、カプセル化に成功しています!!


「名前を呼べないと、使う時に困るんじゃね?」 と思われる人もいるかもしれません。

つまり、そういうことです。 autoを使えば、関数のスコープの外から型の名前を呼べなくても、問題なく使うことができます。


今回は、名前を呼んではいけないあの型、つまりVoldemort Typeについて語ってきました。 「名前を呼んではいけないあの型」よりも、「名前を呼ぶことができないあの型」の方が正確ですね(^_^;) これの応用として、Voldemort FunctionやVoldemort Templateなどが考えられます。 皆さんも、「絶対に名前空間を汚したくない!!」というような時に、ぜひ使ってみてください。

担当:美馬(しかし、Voldemort Typeとは、素晴らしいネーミングセンス!)