On Sunday, 23 June 2013 at 11:04:17 UTC, monarch_dodra wrote:
It's a bit more than that, it's also about limiting template bloat. For example:
To mitigate template bloat, you can downgrade compile-time polymorphism to runtime polymorphism. D provides the facilities for this, e.g. using the above-mentioned pre-made InputRange interface, or using the new `wrap` template from std.typecons in git / 2.064.
It also means iteration will be more expensive than necessary (take will compare both length and empty).
FWIW, `takeExactly` does not.
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.
Then the answer would be to not use `take` on ranges that might change. `take` is one way to limit the length of a range (by a number), but it is not the only way to limit the length of a range.
For example, try implementing a sort (either merge or q) with a non-sliceable range... very very hard...
Are we talking about random-access range types that do not implement opSlice? Wouldn't it be easy to create a wrapper range on top of any random-access range that does implement opSlice?
Otherwise, I don't see how it's even possible (or desirable) to sort a non-random-access range.
It might not sound like much, but have you *tried* using DList?
No. I clearly do not have the same experience with using ranges as you. It's just that the problems that you have presented, as you have presented them, appeared to me to have obvious solutions.
