Going to the Step docs[1] you'll see that its only implemented by integer types and char. If Vec implemented Step, you could iterate over it.
Also, if you're referring to the "contains" guessing puzzle, you have to look at Range::contains docs to see it uses Vec's PartialOrd implementation (basically comparison), in which docs state its elements are compared lexicographically.
Usually in Rust the first thing I'll do when trying to do something very specific (iterate over a Range of Vecs) is try it at the playground (play.rust-lang.org) and/or just look at std docs.
[0] https://doc.rust-lang.org/std/ops/struct.Range.html#impl-Ite... [1] https://doc.rust-lang.org/std/iter/trait.Step.html#implement...
Let's say I have the range [1].. [2], what is in this range?
Well vectors are sorted in lexicographic order, so every vector that starts with 1.
What comes after [1]?
Suppose it's any vector whose first non zero digit is in place n (e.g. n = 2 and the vector is [1, 0, 3, 1]). I can make a vector that comes earlier in the ordering by just inserting another 0 (e.g. [1, 0, 0, 3, 1]). This means that the vector has no non zero digit... but it is obvious that [1] doesn't come after [1], and that [1, 1] comes before [2] so [2] isn't the next vector, so (by proof by contradiction) there actually just isn't a well defined concept of next vector. As a result I definitely can't just list the vectors in a range in order.
I think there is a well-defined next vector, it just isn't very useful. The next vector after [1] for a vector of unsigned integers would have to be [1, 0]. And then [1, 0, 0], [1, 0, 0, 0], etc. (For signed integers substitute T::MIN instead of 0.)
The best thing I can come up with is that such a range defines a path from one tip of a (geomotric) vector to another vector and because vec in rust can have (theoretically) usize elements it's in a usize::MAX dimensional space ;=)
E.g. Iterator is only implemented for things implementing the currently unstable Step trait which for now are mainly integers and char.
E.g. only Range<usize> can be used to index/slice things.
In rust the (useful) trait implementations on `Range<T>` only exist for `T: Step`.
Sure you can create other `Range<T>`'s but you can't use them for anything useful. (Ok, if they are PartialOrd you still can use `contains` and `is_empty`).
The article makes it look like a lot of problems comes from rust being too generic over the range type but that's not the case (expect for contains requiring a reference, but then BigNum's are a thing too).
I.e. the only reason why you can create a `Range<Vec<Mutex<Rc<String>>>>` is because it doesn't hurt anyone to allow me to do so. But I won't be able to use that rang for anything. It won't implement `is_empty`/`contains` nor will it be Iterable. Heck it doesn't even implement `Clone`. But non of the implementations around iterability, is_empty, contains etc. get in practice any problem because of this type being valid.
Instead the mentioned problems come mainly from:
- start <= end not being enforceable at type level as a fallible range constructor would have a horrible UX.
- Range<usize> if used for indexing treating things like 5..0 as "out of bounds" while for iterating it's just an "empty" sequence (which is not nice but a very reasonable decisions generally improving usability in practice due to how the range types are normally used in rust but confusing for some less common use case).
- The person somehow being hung up on the exact definition of "out of bounds" not being clear enough defined in the function documentation of a experimental nightly API which is perma-unstable, i.e. we are basically speaking about internal (but visible) implementation details of the standard library...
pub struct BTreeMap<K, V> {
root: Option<node::Root<K, V>>,
length: usize,
}
The two type parameters are unbounded, this gives flexibility in the implementation because it allows you to define separate `impl` blocks where the bounds are different and more specific to their use case.Have a look, https://doc.rust-lang.org/src/alloc/collections/btree/map.rs...
Sometimes the bounds are just Clone, other times they are more complicated Ord bounds for functions like `get`.
This is the way Rust libraries are written, it's very flexible and it's the right choice IMO.