Bill Baxter wrote:
On Fri, Jan 23, 2009 at 8:10 AM, Christopher Wright <[email protected]> wrote:
Ary Borenszweig wrote:
If the compiler can transform a "foreach" into an opApply call, passing
the foreach body and converting breaks to "return 1" statements... can't
opApply be specified as:
int opApply(void delegate(ref uint) dg) { // note: delegate returns void
}
and the compiler transforms the opApply signature to the one that's used
now, plus converting each dg call to a call and a check of return value !=
0 and return 1 in that case?
This only fails if you wish to take a particular action when the calling
code breaks out of iteration. This is not such a large use case that I think
it worth preserving.
Why do you mean by "fails"? The compiler transforms the foreach's body,
it can transform the opApply's body.
It's not?
foreach(i; things) {
if (i==a) continue;
if (i==b) break;
if (i==d) return;
if (i==c) goto somewhere;
}
Those are all fairly common things to do from inside the 'dg' call.
The int is how the compiler distinguishes which case got you out of
the dg.
--bb
Aaaah... Now I see what's the return value of opApply for. So I tried
your code:
(just the relevant piece)
---
int main(char[][] args) {
int a = 1, b = 2, c = 3, d = 4;
Foo foo = new Foo();
foreach(i; foo) {
if (i==a) continue;
if (i==b) break;
if (i==d) return;
if (i==c) goto somewhere;
}
somewhere:
return 0;
}
---
and DMD spits out this:
---
int main(char[][] args) {
int a = 1, b = 2, c = 3, d = 4;
Foo foo = new Foo;
switch(foo.opApply(delegate (uint __applyArg0) {
{
uint i = __applyArg0;
if(i == cast(uint) a)
return 0;
if(i == cast(uint) b)
return 1;
if(i == cast(uint) d)
return 2;
if(i == cast(uint) c)
return 3;
}
return 0;
} )) {
default:
break;
case 2:
return;
case 3:
goto somewhere;
}
somewhere:
return 0;
}
---
Intersting. The compiler (Walter?) is being smart here. :-)