I'm trying to make this work
use std::collections::HashMap;
struct Test1 {
total: u32,
hash: HashMap<u32, u32>,
}
impl Test1 {
fn new() -> Test1 {
Test1 {
total: 0,
hash: HashMap::new(),
}
}
fn add(&mut self) -> u32 {
self.total += 1;
self.total
}
fn get_or_create(&mut self, id: u32) -> u32 {
match self.hash.get(&id) {
Some(value) => *value,
None => {
let value = self.add();
self.hash.insert(id, value);
value
}
}
}
}
fn main() {
let mut test = Test1::new();
println!("{:?}", test.get_or_create(1));
println!("{:?}", test.get_or_create(1));
}
(playpen)[http://is.gd/hDLEaL]
but I get
<anon>:25:33: 25:37 error: cannot borrow `*self` as mutable because `self.hash` is also borrowed as immutable [E0502]
removing pattern matching doesn't address the problem, but I don't understand why.
With the addition of Non-Lexical Lifetimes in Rust, this problem should no longer be an issue if you're using 1.31.0 with Rust 2018 edition and 1.36.0 with Rust 2015 edition.
This is a problem with the current state of Rust, where borrows are always lexical. That is, they last the entire {}
or block scope. In a match
expression, the borrow performed on self
continues into the Some
and None
blocks. The simplest way to solve this problem is to use an if let
statement. It provides pattern matching, and allows you to use self
in both blocks.
use std::collections::HashMap;
struct Test1 {
total: u32,
hash: HashMap<u32, u32>,
}
impl Test1 {
fn new() -> Test1 {
Test1 {
total: 0,
hash: HashMap::new(),
}
}
fn add(&mut self) -> u32 {
self.total += 1;
self.total
}
fn get_or_create(&mut self, id: u32) -> u32 {
if let Some(&value) = self.hash.get(&id) {
value
} else {
let value = self.add();
self.hash.insert(id, value);
value
}
}
}
fn main() {
let mut test = Test1::new();
println!("{:?}", test.get_or_create(1));
println!("{:?}", test.get_or_create(1));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With