== Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article > FWIW we've been talking a long time ago about a simple lowering - if the > last argument to a function is a delegate, allow moving the delegate's > body outside of the function: > fun(a, b, c) { body } > | > V > fun((a, b, c) { body }); > As far as Walter and I could tell, there are no syntactical issues > created by such a lowering.
Thinking about this a bit more, essentially we are doing the same thing as foreach<->opApply, where we have a function receiving a delegate that will probably be optimized into a local block. There are some key differences, though. Firstly, I can do this with your method: void doOnce(int delegate() dg) { static bool done = false; if (!done) { done = true; writefln("%s", dg()); } } int main() { for (uint i = 0; i < 5; i++) { doOnce() { return 42; } ...do stuff } return 0; } Having a return value sitting in the middle of what looks like a local block is a bit ugly. It seems like main() will end at "return 42". For creating something that operates like a code block, we would never want a return. That brings us to the second problem. Our last parameter for a custom block is always "void delegate()" and our return is always void. There's nothing to be gained by forcing the coder to write both. I'll grant that the delegate passing solution is overall prettier than the macro version I suggested in the original post. The ability to create a doOnce block that can be re-used in multiple places is lost by using delegates since the static variable will only exist in one place, but I can't say that the ability is a major one. The syntax I presented can be easily updated to match your version by the creation of an assumed void delegate() called $. block readLock(IRWLock o) { o.readLock(); scope (exit) o.readUnlock(); $(); }