On Sunday, 23 June 2013 at 10:37:34 UTC, Vladimir Panteleev wrote:
The problem always boils down the fact that while we can get the same iteration scheme, it's never the same range type:

Range r = some_range;
r = r.until!"a == 5"; //Does not compile Until!Range and Range do not match r = r.take(5); //Does not compile: Take!Range and Range do not match

So is it all about reusing a variable?

It's a bit more than that, it's also about limiting template bloat. For example:

R range;
auto r3 = findSplit(range);
void do_it(r3[0]);
void do_it(r3[1]);
void do_it(r3[2]);

This will actually instantiate 2 different do_it functions. This might sound trivial, but these things scale.

It also means iteration will be more expensive than necessary (take will compare both length and empty).

Also, and this is subtle: If you use take, your range will have a fixed size, whereas a "true" bidirectional range will be defined by a start and end point. For example, with the above find split, taken from a DList: If I add elements to the DList, a DList.Range will "grow" to accomodate new elements that where inserted between its bounds. Take!(DList.Range), on the other hand, will *not* grow, and as elements are inserted, the back elements will be pushed outside of the Range.

It might not sound like much, but have you *tried* using DList? Or writing an algo meant to specifically exploit DList mechanics? With ranges, it just doesn't really work quite as well as it should...

Reply via email to