式を勝手に 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(); ... } とさして変わらなくて少しつまらないというか。でも ~ でつなぐのは面白いですね…