Preferred behavior of take() with ranges (value vs reference range)
TheFlyingFiddle via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Nov 8 18:44:47 PST 2015
On Monday, 9 November 2015 at 02:14:58 UTC, Jon D wrote:
> Here's an example of the behavior differences below. It uses
> refRange, but same behavior occurs if the range is created as a
> class rather than a struct.
> --Jon
This is an artifact of struct based ranges being value types.
When you use take the range get's copied into another structure
that is also a range but limits the number of elements you take
from that range.
Basically: take looks something like this: (simplified)
struct Take(Range)
{
size_t count;
Range range;
@property ElementType!Range front() { return range.front; }
@property bool empty() { return count == 0 || range.empty; }
void popFront() { count--; range.popFront; }
}
Code like this:
auto fib1 = ...
//Here fib1 get's copied into first5.
auto first5 = Take(5, fib);
So later when you perform actions on first5 you no longer take
any action on fib1 but instead take action on the copied range
inside of first5. Hence you don't see any consumption of fib1's
elements.
However when you use a refRange / a class the Take range will
take a reference / pointer to the actual range. So now your no
longer working a copy of the range but on the range itself. As
you reuse the same range you will see that consumption has
occured.
If you want a more indepth explanation there were two talks at
Dconf this year that (in part) discussed this topic.
(https://www.youtube.com/watch?v=A8Btr8TPJ8c,
https://www.youtube.com/watch?v=QdMdH7WX2ew&list=PLEDeq48KhndP-mlE-0Bfb_qPIMA4RrrKo&index=14)
More information about the Digitalmars-d-learn
mailing list