为什么我不需要显式借出借来的可变变量? [英] Why do I not need to explicitly lend a borrowed, mutable variable?

查看:52
本文介绍了为什么我不需要显式借出借来的可变变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚编写了一个小型 Rust 程序,它计算斐波那契数并记住计算结果.它有效,但我对原因有点困惑,尤其是递归调用.(这也可能不是惯用语.)

I've just written a small Rust program which calculates Fibonacci numbers and memoizes the calculation. It works, but I'm a little confused about why, especially the recursive call. (It also probably isn't idiomatic.)

程序如下:

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
    }
}

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

Here's how I understand what's going on:

  • main中,let mut cache 的意思是我希望能够改变这个hashmap(或重新分配变量)".
  • main 调用fib 时,它通过&mut cache 说我借给你这个,你被允许改变它."
  • fib 的签名中,cache: &mut Hashmap 的意思是我希望借给一个可变的 HashMap - 借用它并允许变异"
  • In main, let mut cache means "I want to be able to mutate this hashmap (or re-assign the variable)".
  • When main calls fib, it passes &mut cache to say "I'm lending you this, and you're allowed to mutate it."
  • In the signature of fib, cache: &mut Hashmap means "I expect to be lent a mutable HashMap - to borrow it with permission to mutate"

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

(Please correct me if I'm wrong.)

但是当fib递归调用fib(n -1, cache)时,我不需要使用fib(n -1, &mut缓存),如果我这样做,我会得到一个错误:不能借用不可变的局部变量 cache 作为可变的".嗯?它不是一个不可变的局部变量,它是一个可变的借用 - 对吧?

But when fib recurses, calling fib(n -1, cache), I do not need to use fib(n -1, &mut cache), and I get an error if I do: "cannot borrow immutable local variable cache as mutable". Huh? It's not an immutable local variable, it's a mutable borrow - right?

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

If I try fib(n - 1, &cache), I get a slightly different error:

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

这看起来像是在说我期待一个可变引用并得到了一个对可变引用的引用".

Which looks like it's saying "I expected a mutable reference and got a reference to a mutable reference".

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

I know that fib is lending in the recursive call because if it gave up ownership, it couldn't call cache.insert afterwards. And I know that this isn't a special case for recursion, because if I define fib2 to be nearly identical to fib, I can have them recurse via each other and it works fine.

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

推荐答案

您的三点非常到位.当编译器不允许你通过 &mut cache 时,这是因为该值实际上已经被借用了.cache 的类型是 &mut HashMap,所以传递 &mut cache 的结果是 类型的值>&mut &mut HashMap.仅传递 cache 就会得到预期的类型.

Your three points are pretty much spot-on. When the compiler won't allow you to pass &mut cache, it is because the value is actually already borrowed. The type of cache is &mut HashMap<i32, i32>, so passing &mut cache results in a value of type &mut &mut HashMap<i32, i32>. Just passing cache results in the expected type.

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

The specific error message cannot borrow immutable local variable cache as mutable is triggered because the variable cache isn't itself mutable, even though the memory it points to (the HashMap) is. This is because the argument declaration cache: &mut HashMap<i32, i32> doesn't declare a mut variable. This is similar to how a let differs in mutability from a let mut. Rust does support mutable arguments, which in this case would look like mut cache: &mut HashMap<i32, i32>.

这篇关于为什么我不需要显式借出借来的可变变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆