On Wed, Dec 13, 2017 at 12:33:02PM -0700, Jonathan M Davis via Digitalmars-d wrote: > On Wednesday, December 13, 2017 11:33:35 Steven Schveighoffer via > Digitalmars-d wrote: > > I don't think there's a requirement for empty not to do any work, it > > just has to return the same value each time. > > IIRC, when this was discussed previously, it was decided that you > really couldn't do work in empty. The problem is that under some > circumstances at least, it's perfectly legitimate to skip calls to > empty (e.g. if you already know that there's plenty of elements left > in the range, because you've called save previously and have iterated > through at least that many elements in another copy of the range or > because the range has length). it was decided that you really couldn't > do work in empty. It might be legitimate if your range was not a > forward range, but it would only work under cirmustances where it > would be impossible to know whether there are elements left in the > range or not without calling empty - which is not the case when > dealing with forward ranges. [...]
Basically, it comes down to (1) doing the least amount of work necessary to get your job done; and (2) programming defensively, i.e., assume the worst about user code, or, don't assume anything more than what the API dictates. (1) From the range user's POV, the range API essentially says that if .empty is true, then you can call .front and .popFront. Doing the least amount of work means you don't have to call .empty if you already know beforehand it would have returned false. Similarly, it's legal to call .popFront without calling .front (or .empty) in between, if you already know beforehand .empty won't become true in the meantime. (2) From the range author's POV, assuming the worst means not assuming that user code will follow a particular sequence of calls to the range API, other than what is required by the API itself. That is, if your .empty would have returned false, then assume that somebody will call .front or .popFront without calling .empty. Don't assume that someone will always call .empty first. (OTOH, the range API does require that .empty be false before .front and .popFront are called, so you shouldn't need to check .empty yourself in the implementation of .front and .popFront, i.e., avoid doing more work than necessary.) Whether you do work in .empty or .front is not really relevant, as long as ANY sequence of valid range API calls will always produce the same result. And by any sequence of valid calls, of course, I include sequences that don't include .empty if somehow the user code already knows beforehand when .empty will become true. I.e., the sequence { r.popFront; r.popFront; r.popFront; ... ; .front } ought to produce the correct result, as long as .empty never becomes true in the meantime (and .empty does not need to be called explicitly). If you can do work in .empty (or .front) while still fulfilling this requirement, then great. If not, perhaps you should find a different implementation strategy. Everything else is just pudding. T -- Guns don't kill people. Bullets do.