Is there something like a consuming take?

Adam D. Ruppe destructionator at gmail.com
Sat Jul 6 14:40:52 UTC 2019


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.


More information about the Digitalmars-d-learn mailing list