Bug 19980 – File.byLine skips first line in some cases when used inside map!()
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2019-06-17T21:17:17Z
Last change time
2019-07-04T16:40:31Z
Keywords
pull
Assigned to
Vladimir Panteleev
Creator
Florian
Comments
Comment #0 by nairolf — 2019-06-17T21:17:17Z
I have tried to reduce this file as much as I could:
---
import std.stdio, std.algorithm, std.range;
void main( )
{
// Preparation...
auto fw = File("deleteme.txt", "w");
fw.write("Line 1\nLine 2\nLine 3\n");
fw.close();
File[] files = [File("deleteme.txt")];
// Next line contains the bug:
files.map!(f => f.byLine).tee!writeln.each;
}
---
Prints: ["Line 2\r", "Line 3\r"]
Should print: ["Line 1\r", "Line 2\r", "Line 3\r"]
It works correctly if I remove the tee!() and put the writeln in the each!():
files.map!(f => f.byLine).each!writeln;
It also works correctly if there is an ".array" after the map:
files.map!(f => f.byLine).array.tee!writeln.each;
The ".tee!writeln" is just there to generate some readable output. This was originally found by using .joiner, where it also skips the first line:
auto a = files.map!(f => f.byLine).joiner;
Tested on DMD v2.087.0-beta.1 and LDC 1.15.0 (based on DMD v2.085.1).
Comment #1 by dlang-bugzilla — 2019-06-17T22:42:04Z
There's a bunch of things going on here:
1. byLine pops its front eagerly, which means merely constructing a byLine will advance the file pointer.
2. files.map!(f => f.byLine) creates a range whose .front instantiates a new byLine instance, thus advancing the file pointer every time it is evaluated. However, it is not an error to evaluate a range's front multiple times, so there is no bug in tee / each / joiner.
3. Additionally, byLine (ByLineImpl) instances do not each have their own file pointer, which means that if you have more than one byLine instance attached to the same file, advancing one will also advance all others. (Not sure if we should fix this, as it is possible to imagine code relying on this.)
Comment #2 by dlang-bot — 2019-06-17T23:12:14Z
@CyberShadow created dlang/phobos pull request #7077 "Fix Issue 19980 - File.byLine skips first line in some cases when used inside map!()" fixing this issue:
- Fix Issue 19980 - File.byLine skips first line in some cases when used inside map!()
https://github.com/dlang/phobos/pull/7077
Comment #3 by dlang-bot — 2019-07-04T16:40:31Z
dlang/phobos pull request #7077 "Fix Issue 19980 - File.byLine skips first line in some cases when used inside map!()" was merged into master:
- 6197b533ed8c9ccb4d2794573b067bbb514b7b06 by Vladimir Panteleev:
Fix Issue 19980 - File.byLine skips first line in some cases when used inside map!()
https://github.com/dlang/phobos/pull/7077