How can I convince the check check to allow me to cache the values?

The minter hammered me:

use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        let mut cache = &mut self.cache[index];
        match cache.get(&key) {
            Some(r) => {
                return r.clone();
            }
            None => {
                let r = "foo".to_string(); // something smart here
                cache.insert(key, r.clone());
                return r;
            }
        }
    }
}

      

What I get:

error[E0502]: cannot borrow `*cache` as mutable because it is also borrowed as immutable
  --> src/main.rs:16:17
   |
10 |         match cache.get(&key) {
   |               ----- immutable borrow occurs here
...
16 |                 cache.insert(key, r.clone());
   |                 ^^^^^ mutable borrow occurs here
...
19 |         }
   |         - immutable borrow ends here

      

How can I rewrite my code so that it compiles?

+3


source to share


2 answers


Another approach is to use an interface entry

. The only downside to this approach is that it (currently) doesn't use the infrastructure BorrowFrom

that the method uses get

, which makes it less flexible. In your case, this is not a problem, since it get

accepts a key belonging to it. The advantage entry

is that it only does one hash lookup, whereas using get

makes you do two lookups.



use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        self.cache[index]
            .entry(key)
            .or_insert_with(|| "foo".to_string())
            .clone()
    }
}

      

+5


source


The borrowing controller sees it cache.get

as an unchanged loan, even though it returns None

. The easiest way to change the code is to move the insert out of the match, for example:



use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        let mut cache = &mut self.cache[index];
        match cache.get(&key) {
            Some(r) => {
                return r.clone();
            }
            None => (),
        }
        let r = "foo".to_string(); // something smart here
        cache.insert(key, r.clone());
        return r;
    }
}

      

+2


source







All Articles