On Tue, May 13, 2014 at 09:58:09AM -0700, Jonathan M Davis via Digitalmars-d wrote: > On Tue, 13 May 2014 18:38:44 +0200 > Benjamin Thaut via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > > > I know that there was a recent discussion about how the methods of > > ranges should behave. > > > > E.g. > > > > - Does empty always have to be called before calling front or > > popFront? > > Certainly, ranges are pretty much always used this way, but there was > some debate as to whether empty could have work done in it (and thus > _had_ to be called). However, I believe that the consensus was that > yes, empty had to be called (certainly, both Walter and Andrei felt > that way). > > > - Is it allowed to call front multiple times between two calls to > > popFront? > > Definitely. _Lots_ of range-based code would break otherwise - though > there are casese where that can cause problems depending on what you > rely on (e.g. map!(a => to!string(a)) will return equal strings, but > they aren't the _same_ string). > > > Was there a result of that discussion? Is it documented somewhere? > > AFAIK, there's just the semi-recent newsgroup discussion on the > matter, though maybe someone put something up on the wiki. [...]
I second all of the above. In generic code (all range-based code is generic, since otherwise there's no point in using the range abstraction, you should just use the concrete type directly), you cannot assume anything about what .empty, .front, and .popFront() might do apart from what is specified in the range API. Therefore, since .front and .popFront have unspecified behaviour if .empty is false, the only correct way to write range-based code is to call .empty first to determine whether it's OK to call .front and .popFront. Furthermore, it doesn't make sense to restrict .front to be called only once, since otherwise we should simplify the API by merging .front and .popFront and have the same function both return the current element and advance to the next element. The fact that they were designed to be separate calls implies that .front can be called multiple times. Of course, for efficiency purposes range-based code (esp. Phobos code) should try their best to only call .front once. But it should be perfectly permissible to call .front multiple times. Lastly, since the range API is an *abstraction*, it should not dictate any concrete implementation details such as whether .empty can do non-trivial initialization work. Properly-written range-based code should be able to handle all possible implementations of the range API, including those that do non-trivial work in .empty. Of course, that doesn't mean it's a *good* idea for .empty to do non-trivial work. The code is probably cleaner if that work is done somewhere else (like in the ctor or the function that returns the range). But that's an issue for the implementer of the range, not the consumers. The consumers of the range should not depend on one behaviour or the other, so that they will still work correctly when given a range that, for whatever reason, needs to do non-trivial work in .empty. T -- Prosperity breeds contempt, and poverty breeds consent. -- Suck.com