map
.entry(foo)
.and_modify(|bar| {
// value is moved into this closure
// thus preemptive clone here because...
bar.insert(value.clone());
})
.or_insert_with(|| {
// value must be Clone if we want to use it again in this closure
HashSet::from([value])
})
Or I must pay the cost of an additional hash...
if let Some(bar) = map.get(foo) {
// value not moved but...
bar.insert(value);
} else {
// second hash occurs here
map.insert(HashSet::from([value]));
}
Does anyone know a way around this (without unsafe)?
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.
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.