内包表記的な何か

早速作ってみました。

template comp(alias var){
    U[] comp(T, U)(T ary, lazy U dg){
        U[] ret;
        foreach (val; ary){
            var = val;
            ret ~= dg;
        }
        return ret;
    }
}

void main(){
    int x;
    int[] ary = [1, 2, 3, 4, 5];
    foreach(v; comp!(x)(ary, x*x)){
        writefln(v);
    }
}

実行結果。

1
4
9
16
25

本当は、「ary.comp!(x)(x*x)」と書きたい…けど書けない。comp はテンプレートなので当然です。
「alias comp!(x) comp_」とかしておけば「ary.comp_(x*x)」と書けるんですが…わざわざ alias するのもダサい。
そして何よりの不満は、xを定義しないといけないこと…これはどうやら回避不可能のようです。悲しい。


追記:
関係無いテンプレートが入ってたので消しました…消した物は後で紹介するとして、最近こういうミス多いですね!それは兎も角。
http://d.hatena.ne.jp/nazodane/20061211/1165850649
今回は、Dでも簡単に元の配列の各要素を操作した配列を作れるといいな、と言うただそれだけの話でした。
つまるところRubyのmapみたいな物が欲しかったわけです。ただmap相当の物を作ろうとすると delegate を使う必要があって、そうなると。

map!(x)(ary, { return x*x; });

とかになるわけですが、これは面倒臭いので、諦めてlazy使ってます。
あくまでPythonのリスト内包表記の記法を真似するなら…

for__!(T) for_(T)(out T t){
    return new for__!(T)(&t);
}

class for__(T){
    T* ptr_;

    this(T* ptr){
        ptr_ = ptr;
    }

    for___!(T) opIn(T[] ary){
        return new for___!(T)(ptr_, ary);
    }
}

class for___(T){
    T* ptr_;
    T[] ary_;

    this(T* ptr, T[] ary){
        ptr_ = ptr;
        ary_ = ary;
    }

    U[] opShl_r(U)(lazy U dg){
        U[] ret;
        foreach (val; ary_){
            *ptr_ = val;
            ret ~= dg;
        }
        return ret;
    }
}

void main(){
    int x;
    writefln(x*x << (for_(x) in [1, 2, 3, 4, 5])); // [1,4,9,16,25]
    int y;
    writefln(x*y << (for_(x) in [1, 2, 3]) << (for_(y) in [1, 2, 3]));
    // Pythonなら [1,2,3,2,4,6,3,6,9] だけど残念ながら [[1,2,3],[2,4,6],[3,6,9]]
}

こんな感じでしょうか。
本当は「for_(x) in ary」の括弧を外したいんですが、演算子の適用順的に無理そうです。まあ式部分には必要ないみたいなのが救いです。