www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 6214] New: Don't influence foreach iteration on range

reply d-bugmail puremagic.com writes:
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



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: -------
Jun 26 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=6214




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: -------
Jun 26 2011
prev sibling parent d-bugmail puremagic.com writes:
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




 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: -------
Nov 02 2012