4 ms·
Why does Rust allow Ranges for types that don't have comparators in the first place?
by tgb 6y ago
Why does Rust allow Ranges for types that don't have comparators in the first place?
- adamnemecek 6y agoMost of the methods are constrained to types that implement PartialOrd.
- saagarjha 6y agoWhat happens if I make a range bounded on one end by NaN?
- kccqzy 6y agohttps://github.com/rust-lang/rust/blob/2e0edc0f28c5647141bedba02e7a222d3a5dc9c3/library/core/src/ops/range.rs#L137 https://github.com/rust-lang/rust/blob/2e0edc0f28c5647141bed...
- hobofan 6y agoLet's try it! It's empty: https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=be2df2a59e0db7565c3e8b34e065947c https://play.rust-lang.org/?version=beta&mode=debug&edition=...
- dathinab 6y ago- Float ranges can't be used for indexing/slicing slices - Float ranges don't implement Iterator - Rust is clever enough to make is_empty checks NaN robust, so `is_empty` return true - contains checks if it's inside the stard bound and inside the end bounds, but whichever of the bounds is NaN is always not inside the bounds and as such the range won't contain anything (which matches with the behaviour of is_empty) So it works well. But float ranges are kinda useless for anything but the contains/is_empty methods.
- cryptonector 6y agoYes, but why does Rust's Range type not require this?
- dathinab 6y agoYou have no benefits from containing this. No of the problems come from this not being constrained on PartialOrd. Instead they are related to other things like the usability benefit of range construction not being fallible (which is why we can't have a start <= end constraint in the type). Some things could be done differently by constraining the type to always be an integer, but expect `constains` now not needing a reference non of the thinks the article complained about would be different just by constraining it to an integer. In practice many of it's method are anyway only defined for some Range types like you can only use `Range<usize>` for slicing.
- the_mitsuhiko 6y agoThe short answer is that it's quite common not to constraint structs but just the implementations that work with them. You don't notice as much normally as most structs do not expose their internals and the constructors are often constrained.
- slaymaker1907 6y agoAs others have said you don't often put constraints on types in struct definitions. Most of the time if you do it is for using associated types to simplify generics. The reason why constraints on structs isn't a good API design is because it limits future API design scope unnecessarily. In this case, maybe you want to reuse the Range syntax as part of a DSL?
- theon144 6y agoExactly my question. >If you try to enforce that start <= end, you lose the ability to make a Range of non-comparable things What even is a "range of non-comparable things"? Doesn't the very definition, included in the article, imply an ordering because of the "upper" and "lower" bounds? What on earth is a situation where "upper" is not necessarily greater than "lower"?
- dathinab 6y agoIf you try to enforce start <= end you get a fallible range constructor which is a usability nightmare, which is why it's not enforced. It has nothing to do with `Range` being generic. I mean consider: `slice.get(start..end)` against: `(start..end).and_then(|range| slice.get(range))`