I agree with you, there is no reason to redistribute in every popFront . Well, that's not what happens then!
The popFront mechanism popFront very similar to what you presented, and the source is not consumed, but only the array on which you call popFront (because it is still pop). What you implemented is what happens when you slice an array: you get a reference range for the original array:
auto a = [1, 2, 3]; auto s = a[]; s.popFront; assert(s == [2, 3]); assert(a == [1, 2, 3]);
.dup exists to provide a copy of the array so that you can safely modify the copy without changing the original, therefore it copies the original array and provides an input range for that copy. Of course, you can change the copy (which is the point), and popFront will change it, but it still uses pointer arithmetic without changing the source.
auto a = [1, 2, 3]; auto s = a.dup; s.popFront; assert(s = [2, 3]); assert(a = [1, 2, 3]);
.dup may not seem very useful as such, because we use it with arrays, but it is very important to deal with "clean" ranges, since the range is often lazy so as not to consume it. Since the copy of the range is consumed, not the original one, we can safely pass this copy to the function and still have our initial lazy range.
source share