Repost: make foreach(i, a; range) "just work"

w0rp devw0rp at gmail.com
Thu Feb 20 05:04:55 PST 2014


I don't think this is a good idea. Say you have a class with 
range methods and add opApply later. Only the opApply delegate 
receives a type other than size_t for the first argument. Now the 
foreach line infers a differnt type for i and code in the outside 
world will break.

More importantly, this gets in the way of behaviour which may be 
desirable later, foreach being able to unpack tuples from ranges. 
I would like if it was possible to return Tuple!(A, B) from 
front() and write foreach(a, b; range) to interate through those 
thing, unpacking the values with an alias, so this...

foreach(a, b; range) {
}

... could rewrite to roughly this. (There may be a better way.)

foreach(_someInternalName; range) {
     alias a = _someInternalName[0];
     alias b = _someInternalName[1];
}

Then to get a counter with a range, we could follow Python's 
example and use an enumerate function, which would take an 
existing range and wrap it with a counter, so T maps to 
Tuple!(size_t, T).

foreach(index, value; enumerate(range)) {
}

Which is rewritten to roughly this.

foreach(_bla; enumerate(range)) {
     alias index = _bla[0];
     alias value = _bla[1];
}

If we follow Python's example again, we could also support this 
nested unpacking.

// Now written with UFCS instead.
foreach(index, (index_again, value); range.enumerate.enumerate) {
}

Which can rewrite to roughly this.

foreach(_bla; range.enumerate.enumerate) {
     alias index = _bla[0];
     alias index_again = _bla[1][0];
     alias value = _bla[1][1];
}

I got off on kind of a tangent there, but there you go.


More information about the Digitalmars-d mailing list