implicit conversion of expressions to delegates

式を勝手に delegate にしてくれる機能を追加ということで、なかなかみなさん楽しんでおられるようで。最初 statement は delegate にならんしなぁ、とか思ってたんですが、

http://pc8.2ch.net/test/read.cgi/tech/1146656260/582

の do-while を見て、要するに全て expression にすればいいじゃんね、と思って。

int if_(bool delegate() cond, void delegate() yes, void delegate() no) {
    if (cond()) yes(); else no();
    return 0;
}

int for_(void delegate() aex, bool delegate() cex, void delegate() nex,
         void delegate()[] dg ...) {
    for (aex(); cex(); nex()) foreach (d; dg) d();
    return 0;
}

void main() {
    int i, j;
    for_(i=-1, i<=1, i++,
         for_(j=-1, j<=1, j++,
              if_((i|j) == 0, printf(" "), printf("*"))),
         printf("\n"));
}

とかやって遊んでいました。あってそうな気がするのですが、手元で落ちてしまいます。

i@u ~/test/d> ./exp_if_for
***
* *
***
zsh: segmentation fault  ./exp_if_for

まぁニュースグループ2ch を見ても結構バグあるようですし待つことにするとします。今のところ、私が気付いたのは、何度も delegate 作るとまずそう、とか、 ?: 演算子だの . 演算子だのの入る式の左っかわが先に評価されてそう、とかです。

追記: あああと void の式入れられないってのがありましたね。 if_ とかが int 返してる理由はそれ。

最後のは、こんな感じの if-else はうまく行きそうだと思ったけどうまくいかなかった、ということで、バグなのか自分のミスなのか区別しずらい感じ。少し初期の頃のテンプレートを思い出しました。

struct if_ {
    bool cond;
    static if_ opCall(bool delegate() cond, void delegate()[] dg ...) {
        if_ r;
        r.cond = cond();
        if (r.cond) foreach (d; dg) d();
        return r;
    }
    int else_(void delegate()[] dg ...) {
        if (!cond) foreach (d; dg) d();
        return 0;
    }
}

さて今回の追加のバグが落ち着くまでに考えておく課題として、 Ruby やら LISP みたいに、最後に評価した値を返す if だの for だのを書けるか…というのが私の中にあります。第一感ではできませんが。

追記: kurimuraさんが値かえしをやってくださっていますが、なんとなく、 T delegate()[] dg ... で受けるようなやりかたで最後に評価した値を返したいなぁ、と思ってました。ユーザ側で単一 expression になるように工夫させるなら、 (hoge(), fuga(), ...) みたいにさせれば良くて、これでは {hoge(); fuga(); ... } とさして変わらなくて少しつまらないというか。でも ~ でつなぐのは面白いですね…

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h