the source _range to cache elements of
the _buffers to be used by the CircularBlocks member
A _range that participates in the collective ownership of the cached elements
Although opIndex is provided, isRandomAccessRange produces false because this implementation is not a BidirectionalRange at this time.
Todo:
Add opApplyReverse support and BidirectionalRange functions
// In the following typical usage, even though `slide(2)` would visit most // elements more than once, `cached` guarantees that the lambda function // executed by `map` will be executed only once per range element. auto r = iota(4) .map!(i => i * i) // [0, 1, 4, 9] .cached .slide(2) .array; // There are 3 sliding windows of width 2 over 4 elements r.length.shouldBe(3); r[0].shouldBe([0, 1]); r[1].shouldBe([1, 4]); r[2].shouldBe([4, 9]);
// Random access over an InputRange import std.algorithm : splitter; import std.range : popFrontN; // Make an InputRange auto source() { auto lines = "monday,tuesday,wednesday,thursday,friday,saturday,sunday"; return lines.splitter(','); } // The source range does not provide random access: static assert(!__traits(compiles, source[0])); // The cached range does: auto c = source.cached; assert(c[2] == "wednesday"); // Note out-of-order indexing assert(c[1] == "tuesday"); // This element is ready thanks to the previous line c.popFrontN(3); // Now index 0 is another element assert(c[0] == "thursday");
// This version uses an existing buffer. It may never need to allocate // additional heap memory. ubyte[1024][2] buffers; auto r = iota(4) .map!(i => i * i) .cached(buffers) // Will use the provided buffers .slide(2) .array; r.length.shouldBe(3);
A _range algorithm that caches the elements of a _range by evaluating them only once.
Makes a new cache object that will be kept alive collectively with the slices that it produces, first of which is returned.
As a natural benefit of caching, the returned _range is a ForwardRange even if the source _range is an InputRange. Although the returned _range provides opIndex, it is a RandomAccessRange only if the source _range hasLength.
The version that takes buffers may never need to allocate memory if the number of elements never exceed the capacity of the underlying CircularBlocks. (See CircularBlocks.)
This range may mutate the underlying element blocks as needed even inside its front() inout function. For that reason, the behavior of some of its operations are undefined if the provided buffers live on read-only memory.