About foreach loops
Timon Gehr
timon.gehr at gmx.ch
Wed Jun 15 12:05:25 PDT 2011
Steven Schveighoffer wrote:
> I've seen several cases where the syntactic sugar does not work.
>
> two things:
>
> if the compiler detects you never change i, then it can eliminate the
> temporary variable.
It could. Does DMD do that? Let's see:
import std.stdio;
void main(){
foreach(_i;0..100){
writeln(i);
}
}
void main(){
foreach(_i;0..100){
const i=_i;
writeln(i);
}
}
dmd test
1 mov -0x8(%rbp),%edi
2 mov -0x8(%rbp),%ecx
2 mov %rcx,%rdi
dmd test -O
Identical. Nice. Now for something more complex:
import std.stdio;
struct S{
int i;
this(this){writeln("postblit");}
void opUnary(string op:"++")(){++i;}
}
void main(){
foreach(_i;S(0)..S(2)){
//auto i=_i;
alias _i i;
}
}
dmd test -O
With the alias i:
With the auto i:
postblit
postblit
=> Not optimized away, even though it could remove the whole loop.
> We should favor the case which is most useful, not the one which is
> simplest to implement. If you want surprising behavior, use a for loop.
Also if I want guaranteed efficient looping. :o)
>
> When I see foreach(i; xxx), I think i should take on every value contained
> in xxx, whether that be a range, array, or something else. Being able to
> change the elements iterated during the loop is surprising to say the
> least.
>
> Also, think about this:
>
> foreach(i; 0..10)
> {
> i -= 2;
> }
>
> This is a loop that counts *down* to int.min from -1. The idea that this
> should be *expected* behavior is just ludicrous to me.
>
> -Steve
Absolutely. Regarding consistency, it is pretty clear that it should be changed.
Timon
More information about the Digitalmars-d
mailing list