Summary: Don't influence foreach iteration on range
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD

--- Comment #0 from 2011-06-26 01:30:18 PDT ---
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.

Currently you can't solve the problem adding a const(int) to the iteration

import std.stdio;
void main() {
    foreach (const(int) i; 0 .. 10) { // line 3
        write(i, " ");

DMD 2.053 gives:
test.d(3): Error: variable test.main.i cannot modify const


One answer to Caligo:

> This:
>   foreach(i; 0..10){
>     i += 1;
>     write(i, " ");
>   }
> is the same as this:
>   for(int i = 0; i < 10; ++i){
>     i += 1;
>     write(i, " ");
>   }

The problem is this equivalence is hidden. foreach() loops look higher level
than for loops. So programmers expect this higher level look to be associated
with a higher level semantics too. This is why I think currently they are a bit
bug-prone. Modifying the loop variable of a foreach loop is code smell, if I
see it in code I fix it in some way, using a copy of the loop variable, or I
replace the foreach loop with a for loop. So I'd like the compiler to "ignore"
or probably better refuse such modifications to the foreach loop variable, if


This idea has generate a long thread. Most people in the thread seem to
generally agree:

Maybe even Andrei, but I think Walter has not expressed his opinion yet:


The idea is to align the semantics of foreach(x;a..b) to the semantics of
foreach(x;iota(a,b)), because in my opinion a range like 5..10 has to be seen
as the literal for an immutable thing, just like a single number, so you are
not allowed to skip some of its items. On this see also bug 4603

Some people suggest to allow the mutation of the range iteration variable on
request, adding a "ref":
foreach(ref i; 0..10)


See also bug 5255

Configure issuemail:
------- You are receiving this mail because: -------

Reply via email to