Cannot understand this error: HashMap::Keys::rev()

I am trying to ger a reversed iterator

    palette:HashMap<usize, Rgb<u8>>,

// Using it
for (k, _) in self.palette.keys().rev() {

:
:
}

I get the following error that I am finding completely inscrutable

the trait bound `std::collections::hash_map::Keys<'_, usize, image::Rgb<u8>>: std::iter::DoubleEndedIterator` is not satisfied

the trait `std::iter::DoubleEndedIterator` is not implemented for `std::collections::hash_map::Keys<'_, usize, image::Rgb<u8>>`

note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Rev<std::collections::hash_map::Keys<'_, usize, image::Rgb<u8>>>`
note: required because of the requirements on the impl of `std::iter::IntoIterator` for `std::iter::Rev<std::collections::hash_map::Keys<'_, usize, image::Rgb<u8>>>` [E0277]


This is where I read up on this: Keys in std::collections::hash_map - Rust

What is not comprehensible about that, in particular? The error message itself is pretty clear: HashMap's iterator is not reversible. The reason for that is that iteration over a hash map happens in random order, so it doesn't make sense to "reverse" it. The reverse of a random order is still a random order, so you don't gain anything by trying to reverse the iterator.

3 Likes

Use a BTreeMap instead if you need a reverse iterator and the keys are sorted in this collection.

1 Like

Pretty much everything.

True. I meant to sort the Keys (only can be done on nightly be the looks)

But the documentation has rev

		    let mut keys:Vec<usize> = self.palette.iter().
			map(|k| *k.0).collect::<Vec<usize>>();
		    keys.sort();
		    
		    for k in keys.iter().rev() {

That is what I was looking for.

Seems cumborsome. I was hoping for: let keys = self.palette.iter().map(|k| *k.0).collect().sort().rev(); but sort works in place so cannot be chained

I still find the error message utterly inscrutable

There's a trait bound on that method, where Self: DoubleEndedIteratot. Keys doesn't implement that. Hence the error.

3 Likes

Complaining using strong words is not a great way to learn. A bit of humility doesn't hurt – maybe you should look for meaning in the error message and make some effort to understand it, instead of being depreciating as a first reaction.

1 Like

As does any attempt to use the tool which is not the best for the job. If you need the keys to be ordered, it'd be better to use BTreeMap, not HashMap.

5 Likes

You're right. That's not great.

I've opened a ticket on the issue tracker for this one.

6 Likes

Opening an issue for the other problem, with the error messages, is tougher. Being told that "everything" in an error message is bad doesn't give any hints about what the compiler should say instead. It's why the code of conduct says to keep unstructured criticism to a minimum; they need more information about what's exactly wrong in order to fix it.

2 Likes

It's interesting that the error doesn't mention the rev method at all, even though it's bounds weren't satisfied either. It would probably be clearer to call that out first since its the thing that's directly causing the problem.

3 Likes

It does mention it (in the first error).

error[E0277]: the trait bound `std::collections::hash_map::Keys<'_, usize, Rgb<u8>>: DoubleEndedIterator` is not satisfied
    --> src/main.rs:6:34
     |
6    |     for (k, _) in palette.keys().rev() {
     |                                  ^^^ the trait `DoubleEndedIterator` is not implemented for `std::collections::hash_map::Keys<'_, usize, Rgb<u8>>`
     |
note: required by a bound in `rev`
5 Likes

Well that's embarrassing! I guess I was expecting the "method exists... but it's trait bounds were not satisfied" style of error for some reason.