About foreach loops

KennyTM~ kennytm at gmail.com
Wed Jun 15 03:04:07 PDT 2011


On Jun 15, 11 10:20, bearophile wrote:
> This post is about some characteristics of the D foreach that has nagged me for some time.
>
> This is a little Python 2.6 program:
>
>
> for i in xrange(10):
>      i += 1
>      print i,
>
>
> Its output shows that you are allowed to modify the iteration variable (contents of the iteration name), but the iteration goes on with no change:
> 1 2 3 4 5 6 7 8 9 10
>
>
> Similar code in D using foreach shows a different story:
>
> import std.stdio;
> void main() {
>      foreach (i; 0 .. 10) {
>          i += 1;
>          write(i, " ");
>      }
> }
>
> The output:
> 1 3 5 7 9
>
>
> In my opinion this is a bit bug-prone because in real code there is some risk of modifying the iteration variable "i" by mistake. (Note: here I am not talking about D for() loops. They are OK, their semantics is transparent enough. foreach() loops are less transparent and they *look* higher level than for() loops). I'd like the iteration variable to act as being a copy of the true loop variable as in Python. If this is a bit bad for foreach performance, then I'd like the compiler to forbid the mutation of the foreach iteration variable inside the foreach body. Is this even possible?
>
>
> Currently you can't solve the problem adding a const(int) to the iteration variable:
>
> import std.stdio;
> void main() {
>      foreach (const(int) i; 0 .. 10) { // line 3
>          write(i, " ");
>      }
> }
>
>
> DMD gives:
> test.d(3): Error: variable test.main.i cannot modify const
>
>
> This is a related but different thing:
> http://d.puremagic.com/issues/show_bug.cgi?id=5255
>
> Bye,
> bearophile

Perhaps the `foreach` loop

     foreach (i; a .. b)
        loop_body;

should be rewritten into

     for (auto __foreachtemp1234 = a;
          __foreachtemp1234 < b;
          ++ __foreachtemp1234)
     {
        const i = __foreachtmp1234;
        loop_body;
     }

this would prevent the loop index be modified inside the loop body.

Similarly, the indiced array loop

     foreach (i, elem; arr)
        loop_body;

should be rewritten into

     for (size_t __foreachtemp5678 = 0, __foreachtemp5679 = a.length;
          __foreachtemp5678 < __foreachtemp5679;
          ++ __foreachtemp5678)
     {
        const i = __foreachtemp5678;
        auto elem = arr[__foreachtemp5678];
        loop_body;
     }

bearophile, have you filed an enhancement request for this?


More information about the Digitalmars-d mailing list