Let we have the code:
use std::collections::HashMap;
struct Fibonaccer {
cache: HashMap<isize, isize>,
}
impl Fibonaccer {
fn get(&mut self, i: isize)-> &isize {
// if let Some(result) = self.cache.get(&i) {
// return result;
// }
// let get_result = self.cache.get(&i);
// if get_result.is_some() {
// return get_result.unwrap();
// }
if self.cache.get(&i).is_some() {
return self.cache.get(&i).unwrap();
}
let mut value = 1;
if i > 2 {
value = *self.get(i - 1) + *self.get(i - 2);
}
self.cache.entry(i).or_insert(value)
}
}
Here we add value to cache and return reference to cached value. You can say that I can copy result, because it has tiny type, but in common case it can have huge type.
As you can see, I use very strange illogical way to return cached value. Both commented variants are not accepted by borrow checker:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src\main.rs:24:16
|
8 | fn get(&mut self, i: isize)-> &isize {
| - let's call the lifetime of this reference `'1`
9 | if let Some(result) = &self.cache.get(&i) {
| ------------------ immutable borrow occurs here
10 | return result;
| ------ returning this value requires that `self.cache` is borrowed for `'1`
...
24 | value = *self.get(i - 1) + *self.get(i - 2);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
And... I dont understang, why first or second variant are worse than trird.