On Thursday, 2 June 2016 at 14:31:15 UTC, ag0aep6g wrote:
A little terminology: "Slice" is not a synonym for "range".
iota does not return a slice, it returns a range. "Slice" is
being used as a synonym for "dynamic array" (Type[]), and in
the context of the slicing operator (expression[] or
expression[a .. b]).
Now, for the actual question - how to define a range that is
non-empty by definition:
One of the range primitives is popFront. popFront removes one
element from the range. popFront cannot change the type of the
range. So you can't have a type that is a range, and is
guaranteed not to be empty, and can be emptied by calling
popFront.
But you can have a type that is a range, is guaranteed not to
be empty, and *cannot* be emptied by calling popFront: an
infinite range. That's a range that never gets empty no matter
how often popFront is called.
The library recognizes infinite ranges when you define `empty`
like this: `enum bool empty = false;`. There's
std.range.primitives.isInfinite [1] to check for them.
I guess that's not really what you're looking for.
Yes, that's not. :)
I don't think you can otherwise statically check that a range
isn't empty. You could probably make a wrapper that checks once
on construction, but that's still a run-time check. And I don't
see it being particularly useful, because popFront is an
essential parts of ranges.
So this would mean, the contract I use now for run-time check is
ok.
And... well... maybe I can alias two different methods, one which
returns an arbitrary range and one which returns a range, checked
for emptiness in an out contract...
This already would save a lot of code duplication...
You've lost me there. I don't see how non-empty range and
Algebraic connect.
What I mean is: if there would be a possibility to use algebraic
types here (or maybe some kind of template...), then my types
would be able (maybe! did not seen anything similar yet...) to
choose the proper methods for themselves automatically:
As long as my type has a length > 1 it is handled as a range, if
the range has the length=1 it is handled as a single element and
not as a range, if the range has the length=0 it is handled as an
absent element.