-
Notifications
You must be signed in to change notification settings - Fork 7
Ordering for Set
and Map
is not what's expected
#38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Should we even implement Ord and PartialOrd? HashSet and HashMap don't. Given we don't necessarily store the set and map in Consider that BTreeMap and BTreeSet just do |
I think we'd have to generically implement Ord something like this to match the behavior of BTreeSet. Of course it would be much more complicated for non-unit enums. static KEYS_ORDERED: Lazy<[KeyOOO; 5]> = Lazy::new(|| {
let mut keys = [
KeyOOO::Four,
KeyOOO::One,
KeyOOO::Three,
KeyOOO::Five,
KeyOOO::Two,
];
keys.sort_unstable();
keys
});
impl Ord for Set {
fn cmp(&self, other: &Self) -> Ordering {
static KEYS_ORDERED: Lazy<[KeyOOO; 5]> = Lazy::new(|| {
let mut keys = [
KeyOOO::Four,
KeyOOO::One,
KeyOOO::Three,
KeyOOO::Five,
KeyOOO::Two,
];
keys.sort_unstable();
keys
});
let self_iter = KEYS_ORDERED.iter().filter(|&&key| self.contains(key));
let other_iter = KEYS_ORDERED.iter().filter(|&&key| other.contains(key));
self_iter.cmp(other_iter)
}
} |
We should probably not attempt to abide by any particular |
Maybe we should require that PartialOrd and Ord are derived in order to implement Ord and PartialOrd for Storage. I'm pretty sure it's possible to detect the presence of a given derive, because the compiler does it for |
Okay so it looks like, assuming impl<V: Ord> Ord for Storage<V> {
fn cmp(&self, other: &Self) -> Ordering {
self.data
.iter()
.enumerate()
.filter(|(_, x)| x.is_some())
.cmp(
other.data
.iter()
.enumerate()
.filter(|(_, x)| x.is_some())
)
}
} |
Another thing: I don't know if there's a way to use a custom option enum to make this work. In your playground posted to the PR, the following passes: assert!([Option::Some(Foo::First), Option::None] < [Option::None, Option::None]); Which is obviously not what we want. |
I'm trying out a solution in #39. I went down the route of trying to make a custom |
Accidentally an operator? |
Ah sorry yeah, I was typing on my phone. Fixed now. |
See comment.
This primarily stems from how the ordering implementation for
Option
is derived:Without such a definition, some form of wrapper would be needed to change how ordering is done. But any such abstractions also cause issues with potential optimization opportunities.
However it's done, it will become part of the public API of this crate.
The text was updated successfully, but these errors were encountered: