Thoughts about the Entry API


#1

Hi,

I thought that it might be a good idea to add an expect method for the entry API. Currently one can do this

let map: HashMap<i32, i32> = HashMap::new();
let entry = map.entry(7).or_insert_with(|| panic!());

This or_insert_with is just not great for the readability, IMHO.

The other problem with the Entry API usability is that it consumes the key. Is there any reason why it’s not taken by reference?


#2

I agree with your thought about expect but we are waiting for try trait being stabilised.

For the API that consumes the key, it is very intuitive to me actually. In most cases, the key should be Copy or at least Clone so it is not really matter. But in some cases we need to move the value in.

Also, if it is taken by reference, there have to be some lift time notations in the interface, so it would look ugly.


#3

I’m not sure why someone would use the Entry API just to look up a value and panic if it’s absent. Doesn’t get_mut suffice? (It’s wrapping the mutable reference in an Option, but Option one does have expect.)


#4

If you want to print it and remove it from the HashMap if it exists, get_mut won’t let you.


#5
if let Some(existing_value) = map.remove(&7) {
    println!("{}", existing_value);
}

#6

Ah, I see. or_insert[_with] won’t give you the OccupiedEntry, though (it just returns &mut V), which confused me.


#7

Cause the Entry API is meant to insert something into the map when it is not there and return it.

let map = HashMap::new();
assert_eq!(&*map.entry(1).or_insert("foobar".to_string()), "foobar");
assert_eq!(&*map.entry(1).or_insert("new".to_string()), "foobar");

#8

The entry API has many tricky constraints that are non-obvious, which makes the key being a reference or not a big issue. I discussed this a while back here: Head-Desking on Entry API 4.0

The reason insertion methods don’t return an Entry is because this is, in general, non-trivial to do. Inserting can completely restructure the data structure, and reconstituting the entry could be very expensive if this wasn’t desired.

Consider, for instance, a tree without parent pointers. An Entry for such a type is a stack of the searched nodes. Inserting could trigger a total rebalance, requiring a brand-new search stack to be computed.