Rust maps/sets: no way to avoid redundant hash or clone?

Say I have a HashMap<Foo, HashSet<Bar>>,

Or I must pay the price of a redundant Clone...

    .and_modify(|bar| {
        // value is moved into this closure
        // thus preemptive clone here because...
    .or_insert_with(|| {
        // value must be Clone if we want to use it again in this closure

Or I must pay the cost of an additional hash...

if let Some(bar) = map.get(foo) {
    // value not moved but...
} else {
    // second hash occurs here

Does anyone know a way around this (without unsafe)?

Just match on the entry directly.

Edit: but that seems redundant. The whole "check if it exists and if not, insert" kind of dance seems redundant in fact. Why don't you just .insert()? There is no need to check for existence upfront, the map/set will handle both cases correctly.


You probably simply want Entry::or_default, with which the whole logic is just map.entry(foo).or_default().insert(value).


Wow! Of course! Thanks Both!

Do you mean the suggestion provided by @Cerber-Ursi or something different?

Yeah, I noticed there's some additional logic in the else branch. You should just go with .or_default(). It's cleaner because it inserts the identity/null element of the operation (i.e., an empty set), instead of needing to special-case the 1-element situation.

But if the value of map did not impl Default or was not trivially constructible, then I would be best to use the approach you linked in the playground, right?

I'm not sure about what you mean by "trivially constructible". There's surely some way to construct the empty element; you can just use .or_insert_with() if that way is not Default. That still separates construction from manipulating the value.

You'll hardly encounter any case where the idiomatic solution is only expressible with an explicit match, but now you know an alternative if you ever come across one.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.