Bug 19642 – std.range.slide!(No.withPartial) on lengthless forward range: get empty when expecting one window
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P3
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-02-03T22:55:54Z
Last change time
2023-04-24T09:57:28Z
Keywords
pull
Assigned to
No Owner
Creator
kirsybuu
Comments
Comment #0 by kirsybuu — 2019-02-03T22:55:54Z
Failing example (tested in DMD64 D Compiler v2.084.0):
unittest {
auto r1 = recurrence!((a,n) => a[n-1] - 1)(2).until(0);
assert(r1.equal([2,1])); // succeeds
auto r2 = r1.slide!(No.withPartial)(2);
assert(! r2.empty); // fails, should be equal to [[2,1]]
}
The issue appears to be in the "Standard constructor" of the Forward Range version of std.range.Slides when needsEndTracker = true. The nextSource field is initialized using drop(stepSize) and later _empty is set to true if nextSource.empty, which is incorrect behavior because if exactly n elements can be dropped, then the range should contain one window of those n elements.
Suggested fix: do something similar to Slides.popFront() such as
1) change line 8430 of std.range.package.d
nextSource = source.save.drop(windowSize);
to
nextSource = source.save;
auto poppedElems = nextSource.popFrontN(windowSize);
2) change line 8458
if (nextSource.empty)
to
if (poppedElements < windowSize)
Comment #1 by jrdemail2000-dlang — 2019-03-07T06:21:11Z
Another example (encountered writing nlp code manipulating ngrams):
"ab cd".splitter(' ').slide!(No.withPartial)(2)
Should be [["ab", "cd"]], actual is [].
Comment #2 by default_357-line — 2023-04-20T09:00:39Z
Another repro:
```
assert([false, true, false]
.chunkBy!(a => a)
.slide!(No.withPartial)(3)
.count == 1);
```