Currently, one cannot do a foreach statement over a range that also gives the index. This is inconsistent with arrays. I'm not sure if it's the best fix, but at least a temporary fix is to mix this thing into all ranges: template CountForeach(I) { int opApply(int delegate(ref I, ref typeof(this.front())) dg) { I index = 0; int result; foreach(elem; this) { result = dg(index, elem); if(result) { break; } ++index; } return result; } } Usage: struct SomeRange { SomeType front() { return something; } void popFront() { doStuff(); } bool empty() { return amIEmpty(); } mixin CountForeach!size_t; } void main() { SomeRange someRange; foreach(elem; someRange) {} // Uses range interface directly. foreach(i, elem; someRange) {} // Uses the mixin; }
Fixed.
Argh, accidentally marked the wrong bug fixed.
Created attachment 659 [details] patch against dmd r526 Implemented foreach(i, e; r) and foreach_reverse(i, e; r). For reverse iteration with index, r must have a length property.
This has been implemented. Closing as fixed.
Really? Cause this fails to compile for me: unittest { import std.range, std.stdio; foreach (i, e; 100.iota) writeln(i, ": ", e); } Error: cannot infer argument types, expected 1 argument, not 2 Adding types for i and e, or using ranges other than iota, don't seem to change the result. This is on DMD 2.078.2 on Windows. There's a workaround in std.range.enumerate. If that's the implementation you refer to, please include that information. If there's an implementation of this in an upcoming DMD release, please include that information.
(In reply to Simen Kjaeraas from comment #5) > Really? Cause this fails to compile for me: > > unittest { > import std.range, std.stdio; > foreach (i, e; 100.iota) > writeln(i, ": ", e); > } > > Error: cannot infer argument types, expected 1 argument, not 2 > > Adding types for i and e, or using ranges other than iota, don't seem to > change the result. This is on DMD 2.078.2 on Windows. > > There's a workaround in std.range.enumerate. If that's the implementation > you refer to, please include that information. If there's an implementation > of this in an upcoming DMD release, please include that information. This works today. And arguably there many other use cases that could work in the same way, so I do doubt the niche case of 0..n indexing will be worth the enhancement to the compiler especially as it uses the same exact syntax as tuple unpacking. void main() { import std.range, std.stdio; foreach (i, e; 100.iota.enumerate) writeln(i, ": ", e); }
(In reply to Simen Kjaeraas from comment #5) > Really? Cause this fails to compile for me: > > unittest { > import std.range, std.stdio; > foreach (i, e; 100.iota) > writeln(i, ": ", e); > } > > Error: cannot infer argument types, expected 1 argument, not 2 > > Adding types for i and e, or using ranges other than iota, don't seem to > change the result. This is on DMD 2.078.2 on Windows. > > There's a workaround in std.range.enumerate. If that's the implementation > you refer to, please include that information. If there's an implementation > of this in an upcoming DMD release, please include that information. I was referring to the enumarate workaround. Sorry for not being explicit. As Dmitri has pointed out, the additional complexities added to support this aren't worth it since we have a decent workaround.