foreach on interval index by ref increment
bearophile
bearophileHUGS at lycos.com
Sat Jan 21 19:38:48 PST 2012
In the last days Walter and other people are closing and fixing many bugs. But there is one bug that Walter has closed that I am not so sure about:
http://d.puremagic.com/issues/show_bug.cgi?id=5306
Regarding this code:
import core.stdc.stdio;
void main() {
foreach (ref i; 0 .. 10) {
printf("i = %d\n", i);
i++;
}
}
He says it "works as expected":
i = 0
i = 2
i = 4
i = 6
i = 8
But I don't expect and don't like that output (the same probably happens to Python programmers that see that code).
0..10 is a subset of the natural numbers, so it is an immutable entity.
And even if you see the items of a subset of the natural numbers as mutable entities, "i++" means increasing by 1 each one of them, as you see for an array:
import std.stdio;
void main() {
auto array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
foreach (ref x; array)
x++;
writeln(array);
}
That prints:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Or as you see with iota():
import std.stdio, std.range;
void main() {
foreach (ref x; iota(0, 10)) {
x++;
write(x, " ");
}
}
That prints:
1 2 3 4 5 6 7 8 9 10
Skipping to the next number to me looks like "i++" is doing something more like a pointer increment. It's ugly, and looks bug prone. foreach is not a light syntax sugar over a for loop, it's a bit different. I have discussed a similar topic some time ago.
I think some consistency with mathematics and iota() is good to have. Also keep in mind that code like "foreach(i;N..M)" is used _everywhere_ in my programs, so being a so common D idiom it's not a secondary issue.
I suggest to turn the "i" of a foreach(i;N..M) to an immutable. So if you use "ref" it's a "immutable ref" still, so "i++" is a forbidden operation. Programmers that want to increment the loop index inside the loop itself are free to use a normal for loop, and keep the semantics of foreach loops more tidy.
Bye,
bearophile
More information about the Digitalmars-d
mailing list