首页 文章

为什么我不需要明确借出一个借来的可变变量?

提问于
浏览
7

我刚刚写了一个小的Rust程序,它计算Fibonacci数并记住计算 . 它有效,但我有点困惑为什么,特别是递归调用 . (它也可能不是惯用的 . )

这是程序:

use std::collections::HashMap;

fn main() {
    let n = 42; // hardcoded for simplicity
    let mut cache = HashMap::new();
    let answer = fib(n, &mut cache);
    println!("fib of {} is {}", n, answer);
}

fn fib(n: i32, cache: &mut HashMap<i32,i32>) -> i32 {
    if cache.contains_key(&n) {
        return cache[&n];
    } else {
        if n < 1 { panic!("must be >= 1") }

        let answer = if n == 1 {
            0
        } else if n == 2 {
            1
        } else {
            fib(n - 1, cache) + fib(n - 2, cache)
        };
        cache.insert(n, answer);
        answer
    }
}

以下是我了解正在发生的事情:

  • main 中, let mut cache 表示"I want to be able to mutate this hashmap (or re-assign the variable)" .

  • main 调用 fib 时,它传递 &mut cache 来说"I'm lending you this, and you're allowed to mutate it."

  • fib 的签名中, cache: &mut Hashmap 表示"I expect to be lent a mutable HashMap - to borrow it with permission to mutate"

(如果我错了,请纠正我 . )

但是当 fib recurses,调用 fib(n -1, cache) 时,我不需要使用 fib(n -1, &mut cache) ,如果我这样做,我会收到错误:“不能将不可变的局部变量 cache 借用为可变” . 咦?它是一个可变的借用 - 对吗?

如果我尝试 fib(n - 1, &cache) ,我会得到一个稍微不同的错误:

error: mismatched types:
expected `&mut std::collections::hash::map::HashMap<i32, i32>`,
   found `&&mut std::collections::hash::map::HashMap<i32, i32>`

这看起来像是在说“我期待一个可变引用,并引用了一个可变引用” .

我知道 fib 正在递归通话中放贷,因为如果它放弃了所有权,之后就无法调用 cache.insert . 而且我知道这不是递归的特例,因为如果我将 fib2 定义为与 fib 几乎相同,我可以让它们相互递归并且它可以正常工作 .

Why do I not need to explicitly lend a borrowed, mutable variable

1 回答

  • 10

    你的三点非常重要 . 当编译器不允许您传递 &mut cache 时,这是因为该值实际上已经被借用了 . cache 的类型是 &mut HashMap<i32, i32> ,因此传递 &mut cache 会产生类型为 &mut &mut HashMap<i32, i32> 的值 . 只是传递 cache 结果是预期的类型 .

    触发特定错误消息 cannot borrow immutable local variable cache as mutable ,因为变量 cache 本身不可变,即使它指向的内存( HashMap )是 . 这是因为参数声明 cache: &mut HashMap<i32, i32> 没有声明 mut 变量 . 这类似于 let 在可变性方面与 let mut 的区别 . Rust确实支持可变参数,在这种情况下看起来像 mut cache: &mut HashMap<i32, i32> .

相关问题