On 2010-01-29 11:54:41 -0500, "Steven Schveighoffer" <[email protected]> said:

On Fri, 29 Jan 2010 11:33:17 -0500, Michel Fortin <[email protected]> wrote:

On 2010-01-29 11:18:46 -0500, Andrei Alexandrescu <[email protected]> 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
[email protected]
http://michelf.com/

Reply via email to