On Saturday, 6 July 2019 at 14:12:36 UTC, berni wrote:
Meanwhile I encountered, that take() sometimes consumes and sometimes not.

It depends on what you're passing.

So take is defined as just getting the first N elements from the given range. So what happens next depends on what it is "taking" from (I don't like the name "take" exactly because that implies, well, taking. What the function really does is more like "view into first N elements".


With input ranges, iterating over them consumes it implicitly, so you could say that take *always* consumes input ranges (at least once it gets iterated over).

But, it will frequently consume a copy of the range instead of the one you have at the top level, since ranges are passed by value.

If you want it to be seen outside, `ref` is the general answer. You might find success with refRange in some cases.

http://dpldocs.info/experimental-docs/std.range.refRange.html



But if you are passing something with slicing, like a plain array, take will never actually consume it, and instead just slice the input, even if it is ref. This gets the view of those first elements in cheaper way.

So going back to your original definition:

I want to copy the first n items of a range to an array, removing these items from the range.

As far as I know, none of the std.range functions are defined to do this.

I'd probably write your own that:

1) takes the range by ref so changes are visible outside
2) iterates over it with popFront
3) returns the copy

that should fulfill all the requirements. you could slightly optimize arrays (or other hasSlicing things) like

int[] yourFunction(ref int[] arr, int n) {
   auto ret = arr[0 .. n];
   arr = arr[n .. $];
   return ret;
}


that is, just slicing and consuming in one go for each side and then you don't even have to actually copy it, just return the slice.

Reply via email to