为什么我不需要显式借出借用的可变变量?

2023-11-25

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

这是程序:

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

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

  • In main, let mut cache意思是“我希望能够改变这个哈希图(或重新分配变量)”。
  • When main calls fib,它通过了&mut cache说“我借给你这个,你可以改变它。”
  • 在签名中fib, cache: &mut Hashmap意思是“我希望借用一个可变的 HashMap - 在允许变异的情况下借用它”

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

但当fib递归,调用fib(n -1, cache),我不需要使用fib(n -1, &mut cache),如果我这样做,我会得到一个错误:“无法借用不可变的局部变量cacheas mutable”。嗯?这不是一个不可变的局部变量,它是一个可变的借用 - 对吧?

如果我尝试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,我可以让它们相互递归,并且效果很好。

为什么我不需要显式借出借用的可变变量?


你的三点非常准确。当编译器不允许你通过时&mut cache,这是因为该值实际上已经被借用了。的类型cache is &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与 a 的可变性不同let mut。 Rust 确实支持可变参数,在这种情况下看起来像mut cache: &mut HashMap<i32, i32>.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我不需要显式借出借用的可变变量? 的相关文章

随机推荐

  • 如何在 string.replace 中输入正则表达式?

    我需要一些关于声明正则表达式的帮助 我的输入如下 this is a paragraph with lt 1 gt in between and then there are cases where the lt 99 gt number
  • XMLHttpRequest upload.onprogress 立即完成

    我正在尝试使用 HTML5 制作一个带有进度表的文件上传器 这是我的代码
  • C++/CLI:相对于 C# 的优势

    与 C 相比 托管 C CLI 有什么主要优势吗 绝对不是我认为的语法 因为 C CLI 中的以下代码非常丑陋 C CLI 代码 Out List
  • 日志方法之间的区别

    我是 android 新手 我使用以下方法打印 log cat Log w Tag String text 并记录文本打印 但经过一段时间的搜索后 我找到了更多打印 logcat 的方法 例如 Log v Log d 现在我对这些方法感到困
  • 跨 JavaEE Web 服务使用单个 MongoClient

    在阅读了 mongo 文档后 该文档说 MongoClient 的每个实例都处理自己的池 我该如何在整个应用程序中只拥有一个实例呢 这看起来可能是使用单例 bean 的场景 但这似乎会违背连接池的目的 如果一次只有一个用户能够访问包含 Mo
  • 传递给 pytest 夹具的参数可以作为变量传递吗?

    我有两个简单的测试设置 我试图将它们分组到一个夹具中 并希望测试函数将 参数 传递给夹具 这是一个人为的例子 来解释我的问题 假设我有以下 pytest 夹具 pytest fixture scope module params param
  • DataTable.Select日期格式问题

    我正在使用 DataTable Select 在日期范围内过滤数据表 我的条件字符串是 CreatedOn gt 03 11 2009 00 00 00 AND CreatedOn lt 03 11 2009 23 59 00 此过滤器不返
  • UnicodeEncodeError:“ascii”编解码器无法对特殊名称的字符进行编码[重复]

    这个问题在这里已经有答案了 我的 python 版本 2 7 脚本运行良好 可以从本地 html 文件获取一些公司名称 但是当涉及到某些特定的国家 地区名称时 它会给出此错误 UnicodeEncodeError ascii 编解码器无法编
  • rgba 在 IE9 中不工作

    由于某种原因 我无法使用 IE9 在 CSS 中使用 rgba 我已经使用 Chrome 进行了测试 效果很好 不知道出了什么问题 我的 HTML 是
  • Eclipse + Maven:强制执行环境“JavaSE-1.6”而不是固定的JDK

    我使用 Eclipse 作为 IDE 并在其外部使用 Maven 以使所有依赖项保持最新并更新 Eclipse 项目 在 Eclipse 中 我通常指定 JRE 系统库作为任何 Java 项目的执行环境 通常是 JavaSE 1 6 在 p
  • CSS 将文本旋转 n 度,但不旋转边界框?

    我知道 CSStransform rotate属性 以及用于制作有角度的方法div元素 但有一个非常重要的设计元素我无法在任何地方找到解决 如何保持边界框的角度 当我创建有角度的 div 元素时 我使用一个旋转的包装元素n度数 然后是子元素
  • C#:如何使用类型转换器本地化枚举

    阅读后我试图了解如何使用类型转换器这个答案我的其他问题之一 但我不确定我是否完全明白 在我的特定情况下 我想通过根据枚举成员是什么来获取资源字符串 将枚举成员 转换 为本地化字符串 例如 如果我有这个枚举 public enum Sever
  • Mongo复杂排序?

    我知道如何按多个字段对 MongoDB 中的查询进行排序 例如 db coll find sort a 1 b 1 我可以使用用户定义的函数进行排序吗 例如 假设 a 和 b 是整数 则通过 a 和 b 之间的差 a b Thanks UP
  • 如何安装特定版本的 Erlang/OTP?

    我继承了一个带有木偶 流浪者 虚拟框设置的项目 vagrant 的规定正在破坏我的 erlangs 周围的rabbitmq server 错误 gt default err Stage main Rabbitmq Install Packa
  • TensorFlow:兼容性弃用警告

    注意 我的第一个问题在这里 请原谅缺乏细节或信息 如果需要的话 我们非常乐意澄清 我在 Mac 上运行 TensorFlow 1 0 0 并且在使用 learn Estimator 类时不断收到此警告 警告 tensorflow 来自 25
  • 使用React手动刷新react-query onClick

    当我重新获取查询时 当我有 onClick 按钮时 它会进入 正在更新 状态 但我希望重新获取查询并显示 正在加载 状态 我的代码是 https stackblitz com edit react ts jfq8ve file index
  • php chmod() 不更改权限

    我的图片上传脚本有问题 我知道有数百个相同的问题 但我还没有找到适合我的问题 upload dir images postcards chmod upload dir 777 if is writable upload dir echo T
  • 永久代是堆的一部分还是位于 jvm 中的不同空间中

    我看到了很多关于这个问题的评论 有人说是 有人说不是 而且许多答案都是模棱两可的 任何人都可以用更简单的术语描述它所在的位置吗 在一篇文章中 我什至看到有人说它与类内存共享相同的内存位置 其中类由类加载器加载 这是真的吗 原始 可能是错误的
  • Web语音API:在iOS safari上一致获取支持的语音合成声音

    我正在尝试获取 iOS Safari 上支持的语音合成声音列表 根据 API 我应该能够通过调用获取一系列声音 window speechSynthesis getVoices 有时这会给我声音列表 有时则不会 请参阅以下 jsfiddle
  • 为什么我不需要显式借出借用的可变变量?

    我刚刚编写了一个小的 Rust 程序 它计算斐波那契数并记住计算结果 它有效 但我对为什么有点困惑 尤其是递归调用 这也可能不是惯用语 这是程序 use std collections HashMap fn main let n 42 ha