我想将memoization添加到一个可能有点昂贵的函数中。我尝试在下面做一个最小的例子来证明错误。
use std::collections::{HashMap};
struct Foo {
data: i64,
memo: HashMap<i64, String>
}
impl Foo {
fn new(data: i64) -> Foo {
let memo = HashMap::new();
Foo {data, memo}
}
fn f(&self, x: i64) -> String {
(self.data + x).to_string()
}
fn f_cached(&mut self, x: i64) -> String {
match self.memo.get(&x) {
Some(result) => result.clone(),
None => {
let result = self.f(x);
self.memo.insert(x, result.clone());
result
}
}
}
}
我删除下面的f_cached
函数,然后编译所有内容,但缓存版本拒绝编译;我得到的错误是:
error[E0502]: cannot borrow `self.memo` as mutable because it is also borrowed as immutable
--> src/main.rs:173:17
|
169 | match self.memo.get(&x) {
| --------- immutable borrow occurs here
...
173 | self.memo.insert(x, result.clone());
| ^^^^^^^^^ mutable borrow occurs here
...
176 | }
| - immutable borrow ends here
我尝试过基本逻辑的各种重写,例如将self.memo.get(&x)
分配给变量,使用if let
等等,但是所有内容都会产生相同或不同类型的错误。当然,它并没有看起来,就像代码中出现任何不安全因素一样。
答案 0 :(得分:0)
虽然其他引用是正确的,但请注意,在编译器的夜间版本中,可以使用称为非词汇生命周期的功能,启用该功能后,可以使您的代码可编译:
#![feature(nll)]
use std::collections::{HashMap};
struct Foo {
data: i64,
memo: HashMap<i64, String>
}
impl Foo {
fn new(data: i64) -> Foo {
let memo = HashMap::new();
Foo {data, memo}
}
fn f(&self, x: i64) -> String {
(self.data + x).to_string()
}
fn f_cached(&mut self, x: i64) -> String {
match self.memo.get(&x) {
Some(result) => result.clone(),
None => {
let result = self.f(x);
self.memo.insert(x, result.clone());
result
}
}
}
}
fn main() {}
NLL功能的跟踪问题是here。它目前正在积极开发中,并且可能在最近的将来不会稳定,但它是Rust的发展方向,如果您对使用夜间版本的编译器感到满意,那么您可以使用#![feature(nll)]
。