Another foreach idea.
Kirk McDonald
kirklin.mcdonald at gmail.com
Wed Jun 7 21:40:45 PDT 2006
Dave wrote:
>
> Instead of:
>
> for(int i = 1_000; i < 1_000_000; i++) {}
>
> How about:
>
> foreach(idx; 1_000 .. 1_000_000)
> {
> // 1_000 to 999_999 or 1_000 to 1_000_000?
> // type inferred 'idx' would be an int or long
> // depending on 32 bit or 64 bit hardware
> }
>
> or simply:
>
> size_t x = 1_000_000;
>
> foreach(idx; x)
> {
> // 0 to 999_999 or 1 to 1_000_000?
> // type inferred 'idx' is size_t
> }
>
> The rational would be not only for brevity but also the reasons given
> here: http://digitalmars.com/d/faq.html#foreach
>
> I can see the problems already - 0 or 1 based? 0 based to be consistent
> with how many for loops are written now and with array indexing (even
> though presumably you'd then use foreach with the array itself)? Or 1
> based because then it would be WYSIWYG.
>
> - Dave
This is very much like Python's behavior. In that language, there isn't
a "for" loop as such, only a "foreach" loop. To loop a counter from 0 to
9, you'd write:
for i in range(10):
print i
Where "range" is a function that returns a list containing a range of
integers, with a footprint like:
range(start=0, end, step=1)
(Python allows default values in places that D does not.) There is also
an xrange function, which returns a generator rather than a whole list,
which can be more useful for large ranges.
To loop from 10 to 99, you'd write:
for i in range(10, 100):
print i
In short, all you need is a "range" function that returns an array of
integers, or (alternately) a generator... something like this:
private import std.stdio;
class range {
protected:
int m_start, m_end;
int m_step = 1;
public:
// Can't just specify (end, step), but there's nothing
// to be done for that.
this(int end) {
m_end = end;
}
this(int start, int end) {
m_start = start;
this(end);
}
this(int start, int end, int step) {
m_step = step;
this(start, end);
}
// Convenience functions
static range opCall(int end) {
return new range(end);
}
static range opCall(int start, int end) {
return new range(start, end);
}
static range opCall(int start, int end, int step) {
return new range(start, end, step);
}
// Compares whether i has reached the end
private bool cmp(int i) {
if (m_step > 0 && i < m_end) return true;
else if (m_step < 0 && i > m_end) return true;
else return false;
}
int opApply(int delegate(inout int) dg) {
int result = 0;
for (int i=m_start; this.cmp(i); i+=m_step) {
result = dg(i);
if (result) break;
}
return result;
}
}
void main() {
foreach(i; range(10)) {
writefln("%s", i);
}
foreach(j; range(10, 20)) {
writefln("%s", j);
}
foreach(k; range(0, 10, 2)) {
writefln("%s", k);
}
}
Though honestly, a regular for loop isn't much of a burden.
-Kirk McDonald
More information about the Digitalmars-d
mailing list