Here’s one use case for a>..
syntax and for the accompanying std::ops::RangeFromExclusive
type. This is something I actually encountered with, so it’s not a contrived example.
You have a type BoundedIndex
which encapsulates an integer and guarantees that any code located outside the module of BoundedIndex
that asks for the value of the encapsulated integer is going to get an answer that’s within a certain range, say [0, 9] in this case. This type is useful for safe indexing without bounds checking into fixed-size arrays like [T; 10]
. If you try to add an integer to a BoundedIndex
, the resulting index is checked to be within the valid range like so:
impl Add<usize> for BoundedIndex {
type Output = BoundedIndex;
fn add(self, value: usize) -> BoundedIndex {
assert!(value < 10 - self.index);
BoundedIndex { index: self.index + value }
}
}
In the module of BoundedIndex
you have also a type Iter
which implements the Iterator
trait. It’s something like:
#[derive(Copy)]
pub struct Iter {
front: BoundedIndex,
after: BoundedIndex,
}
To create an Iter
, you call an associated trait method called slice
on BoundedIndex
:
pub trait Slice<R> {
fn slice(range: R) -> Iter<Self>;
}
// Here's the implementation for the regular "from-inclusive" `RangeFrom`:
impl Slice<RangeFrom<BoundedIndex>> for BoundedIndex {
fn slice(range: RangeFrom<BoundedIndex>) -> Iter<BoundedIndex> {
Iter {
front: BoundedIndex { index: range.start.index },
after: BoundedIndex { index: 10 }, // The "end" is one off bounds
}
}
}
// And here's the implementation for the hypothetical `RangeFromExclusive`:
impl Slice<RangeFromExclusive<BoundedIndex>> for BoundedIndex {
fn slice(range: RangeFromExclusive<BoundedIndex>) -> Iter<BoundedIndex> {
Iter {
// We know that front index is going to be at most one off bounds
// (which is fine, that would just mean it's an empty slice).
front: BoundedIndex { index: range.excluded_start.index + 1 },
after: BoundedIndex { index: 10 },
}
}
}
Now, compare these two different ways to try to create the exactly same slice:
-
Using
RangeFrom
:BoundedIndex::slice(x+1 ..)
-
Using
RangeFromExclusive
:BoundedIndex::slice(x >..)
…where x
is a BoundedIndex
.
The first case, using RangeFrom
, goes through the add
method and therefore has to check that the resulting index is within the valid range of values. Also, notice that if x
is at the maximum index value 9, then this will cause panic in the add
method.
The second case, using RangeFromExclusive
, is more optimized because it doesn’t have to go through the add
method nor bounds check the value of the index within x
. This way of creating the slice won’t ever panic.