我试图创建一个简单的memoisation风格的调用循环。它看起来像这样:
fn dive(seen: u32, d: u32, r: u32, routes: &mut HashMap<(u32, u32), u32>) -> u32 {
match routes.get(&(cmp::max(d, r), cmp::min(d, r))) {
Some(v) => seen + *v,
None => {
let result = dive(0, d-1, r, routes) + dive(0, d, r-1, routes);
routes.insert((cmp::max(d, r), cmp::min(d, r)), result);
seen + result
}
}
但是,我遇到了问题,因为路线是为了匹配而不可靠地借用的,然后在有效的生命周期内可变地传递给下面的dives
。
我怎样才能让它发挥作用?可以通过简单地复制&#39;来解决。某种程度上不可变的价值?或者我是否需要修复控制流程?
答案 0 :(得分:3)
我知道这已经得到了回答,但是寻找它并没有取得丰硕的成果。如果有人发现了欺骗行为,请随意标记。
问题是在Rust中,借用范围目前是 lexical - 它们对应于代码区域,以结束大括号结束。
在您的示例中,借用routes
会持续整个match
块,其中包含None
个案。更聪明的编译器将能够看到None
情况没有引用routes
并允许您更改它。现在,你必须让你的代码更加丑陋:
use std::collections::HashMap;
use std::cmp;
fn dive(seen: u32, d: u32, r: u32, routes: &mut HashMap<(u32, u32), u32>) -> u32 {
let key = (cmp::max(d, r), cmp::min(d, r));
if let Some(v) = routes.get(&key) {
return seen + *v;
}
let result = dive(0, d-1, r, routes) + dive(0, d, r-1, routes);
routes.insert(key, result);
seen + result
}
fn main() {}
这将代码拆分为两个不同的范围,澄清了第一个范围内只需要借用。
这有希望改变。最初的问题是borrow scopes should not always be lexical,该问题已被关闭,有利于an RFC。在目前的时间点,RFC被推迟。不幸的是,从词汇范围转向非词汇范围借用可能会使某些类型的事情难以推理。