foreachの新機能

D言語スレで出てきたので,2.021におけるforeachの変更の超簡単な例でも書いておく.

class Range(T)
{
    int index;
    int length;
    T[] range;

    this(T[] range)
    {
        this.range = range;
        length     = range.length;
    }

    T head()
    {
        return range[index];
    }

    void next()
    {
        index++;
    }

    bool empty()
    {
        return index >= length;
    }
}

void main()
{
    auto range = new Range!(int)([1, 2, 3]);

    foreach (e; range)
        writefln(e);
}

で,これが2.021だと1,2,3と表示されるけど,2.020以前だと

range.d(35): Error: cannot infer type for e

となる.

今回の変更のrangeサポートというのは,dmdディレクトリ以下のstatement.cにあるsemanticのTstructを見れば分かる.

/* Look for range iteration, i.e. the properties
 * .empty, .next, .retreat, .head and .rear
 *    foreach (e; range) { ... }
 * translates to:
 *    for (auto __r = range; !__r.empty; __r.next)
 *    {   auto e = __r.head;
 *        ...
 *    }
 */

というコメントがあって,実装の方でこれらを出力している.ということで今回のはforeachに指定のメソッドを持ったクラスや構造体を渡すとforに置き換えてくれるというもの(toeとかretreatがあるから双方向もOK?).


今までだと内部イテレータとして,opApplyやそれと同じシグネチャのメソッドを別途定義する必要があったわけだけど,これで外部イテレータとしても使えるようになった.無駄なメソッドを削れるかもしれないし,まぁ有用な機能は増えて損はない.
Rangeがどんなものかはここを参照