On Friday, 28 March 2014 at 02:14:40 UTC, H. S. Teoh wrote:
I'm with Walter on this one. Generic code should NOT assume
anything
about a range it was given, and therefore it should call .empty
before
calling .front or .popFront. If you "know" that a particular
range
doesn't require calling .empty beforehand, then by definition
your code
is no longer generic, and you just have to live with the
consequences of
that. Nothing stops you, for example, from exposing a .get
function or
whatever else, *in addition* to the standard range API. Then
code that
knows how to deal with .get will use it, and your range remains
usable
with other generic code.
It's not that *you* know a particular range doesn't need "empty"
called, it's that the algorithm you are using has already
previously validated there are elements in it.
For example, the splitter algorithm will first save a copy of its
range, and then walk it, searching for the "splitting" elements.
It then realizes it has walked N elements.
From there, it takes the original range, and packs it into a
"takeExactly(N)" of the original range. Iterating that
"takeExactly(N)" is faster than a raw "take", *because*
"takeExactly" was already promised that the range holds N
elements, and as such, *doesn't* check for empty.
Ditto for "findSplit".
And again, there are functions, such as "copy", then simply
*require* that a certain range have at least a certain amount of
elements. Why check for it, if not providing it is a violation of
its interface.
On Thursday, 27 March 2014 at 23:52:46 UTC, Walter Bright wrote:
I know that you want to get rid of empty. But getting rid of
empty means that front may fail. This is why there is an empty,
and any generic code MUST respect that.
Front only fails *if* the range is empty. Not if you fail to call
empty. Generic code respects that.
What you can do is, in your range:
enum empty = true;
That's not the same. That's making the assumption your range will
*never* be empty, which is a whole other concept (infinite
ranges).