Thread overview
[Issue 6214] New: Don't influence foreach iteration on range
Nov 03, 2012
Kenji Hara
June 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6214

           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
        AssignedTo: nobody@puremagic.com
        ReportedBy: bearophile_hugs@eml.cc


--- Comment #0 from bearophile_hugs@eml.cc 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
variable:

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 possible.

-------------------

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

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=138630 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=138852

Maybe even Andrei, but I think Walter has not expressed his opinion yet: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=138718

-------------------

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: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=6214



--- Comment #1 from bearophile_hugs@eml.cc 2011-06-26 02:07:01 PDT ---
This is an older enhancement requst, bug 5306

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 03, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=6214


Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |DUPLICATE


--- Comment #2 from Kenji Hara <k.hara.pg@gmail.com> 2012-11-02 21:12:30 PDT ---
(In reply to comment #0)
> 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.

This is now progressing by fixing bug 6652. So I'll mark this as a dup of it.


> 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 2.053 gives:
> test.d(3): Error: variable test.main.i cannot modify const

This is a dup of bug 4090, and it is mostly fixed in 2.061head.

*** This issue has been marked as a duplicate of issue 6652 ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------