Rust: How to combine the Entry API with owned data?

525 views Asked by At

I have a HashMap and would like to update a value if it exists and otherwise add a default one. Normally I would do it like this:

some_map.entry(some_key)
    .and_modify(|e| modify(e))
    .or_insert(default)

But now my modify has type fn(T)->T, but the borrow checker obviously won’t allow me to write:

some_map.entry(some_key)
    .and_modify(|e| *e = modify(*e))
    .or_insert(default)

What is the preferred way of doing this in Rust? Should I just use remove and insert?

1

There are 1 answers

2
Masklinn On BEST ANSWER

Assuming you can create an empty version of your T for cheap, you could use mem::replace:

some_map.entry(some_key)
    .and_modify(|e| {
        // swaps the second parameter in and returns the value which was there
        let mut v = mem::replace(e, T::empty());
        v = modify(v);
        // puts the value back in and discards the empty one
        mem::replace(e, v);
    })
    .or_insert(default)

this assumes modify does not panic though, otherwise you'll find yourself with the "empty" value staying in your map. But you'd have a similar issue with remove / insert.