Accessors, byLine, input ranges
Michel Fortin
michel.fortin at michelf.com
Fri Jan 29 09:14:13 PST 2010
On 2010-01-29 11:54:41 -0500, "Steven Schveighoffer"
<schveiguy at yahoo.com> said:
> On Fri, 29 Jan 2010 11:33:17 -0500, Michel Fortin
> <michel.fortin at michelf.com> wrote:
>
>> On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> said:
>>
>>> It should work for stream ranges if front() checks the "filled" flag
>>> and eats the next line if false, and popFront clears the "filled" flag.
>>
>> So now you want the front to fetch from stdin on the first call? It's
>> the same problem as 'byLine' eating the first line when you create it:
>> neither one or the other should affect the stream.
>
> No, you're reaching here :) What Andrei is doing is acknowledging that
> front has already performed the job of popFront. Because of the
> nature of streams, you cannot get the data from the stream, and leave
> it on the stream at the same time. It's just not feasible.
>
> What the solution Andrei came up with does is to make stream ranges
> behave as close as possible to forward ranges. That small
> inconsistency will not hurt you because most of the time you are not
> calling front for an element you don't intend to use. And even within
> that paradigm, you are even less likely to use the stream in another
> capacity.
"will not hurt because most of the time"... surely you meant "will not
hurt most of the time because". You're acknowledging it's an
inconsistency and that it'll hurt.
> In other words, as the last usage of a range in an algorithm function, this:
>
> r.front;
> r.popFront();
>
> is way more likely than:
>
> r.popFront()
> r.front;
Yeah, it's less likely to be a problem. But "less likely to be a
problem" does still does not make things reliable. Something reliable
works all the time, or it just doesn't work and tells you.
And I'd argue that it's very likely that an algorithm hits the problem,
check this:
skipEmptyLines(stdin.byLine);
string line = stdin.readln;
void skipEmptyLines(R)(R range) {
while (!range.empty && range.front == "")
range.popFront;
}
skipEmptyLine works right with ranges, but not with a stream. On the
last loop, it calls range.front, which removes a line from the stream,
and then say it's finished.
The truth is that this algorithm doesn't work with streams as it relies
on a buffer being available. But it still compiles, silently
introducing a bogus behaviour. If byLine defined only a 'take'
function, we wouldn't have this problem as skipEmptyLines wouldn't
compile, forcing you to use some kind of buffered stream or another
algorithm that works correctly with streams.
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
More information about the Digitalmars-d
mailing list