可变地传递一个不可改变的借来的变量

时间:2015-08-24 21:00:01

标签: rust

我试图创建一个简单的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;来解决。某种程度上不可变的价值?或者我是否需要修复控制流程?

1 个答案:

答案 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被推迟。不幸的是,从词汇范围转向非词汇范围借用可能会使某些类型的事情难以推理。