10..1
cannot be changed to mean the sequence "10, 9, 8, ..., 2" because it's already a valid empty range:
assert_eq!((10..1).contains(&9), false);
Even if backwards compatibility was not a concern, I would still prefer the current meaning, because it's much simpler: a..b
means the range of values x
that are both a <= x
and x < b
, so you don't even have to compare the endpoints. Allowing reversed ranges would turn that logic into something like ((a <= x) & (x < b)) | ((b < x) & (x <= a))
(not just min(a,b) <= x < max(a,b)
because for consistency a
should probably be included and b
excluded regardless of their mutual order).
For (statically) reversed iteration, Iterator::rev
seems sufficient. For a (statically) reversed range, you can sort of do
use std::cmp::Reverse;
assert_eq!((Reverse(10)..Reverse(1)).contains(&Reverse(9)), true);
... although it's not very useful when you can't use that for iteration or indexing. Admittedly the repetition is noisy, but it's the same issue as when using BinaryHeap
and need a min heap.
I would expect a range with a dynamic direction is rarely needed, and better served by something more general like (0..len).map(|n| start + step * n)
.
edit: Actually, connecting the dots from my two footnotes to the other question that was asked, Reverse<usize>
and Range<Reverse<usize>>
might be natural types for indexing something from the back:
let v = ['a','b','c','d','e','f'];
assert_eq!(v[Reverse(0)], 'f');
assert_eq!(v[Reverse(1)], 'e');
assert_eq!(v[Reverse(2)..], ['d','e','f']);
assert_eq!(v[Reverse(3)..Reverse(1)], ['c','d']);
This mostly avoids issues of the python-solution where using an index that is unexpectedly negative is hard to debug because it's not an error.