如何递归传递可变引用? [英] How do I recursively pass a mutable reference?

查看:60
本文介绍了如何递归传递可变引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Rust 中解决这个问题.

I am attempting to solve this problem in Rust.

这是我的非编译 Rust 代码:

Here is my non-compiling Rust code:

use std::collections::HashMap;

fn main() {
    // initialize HashMap
    let mut fibs: HashMap<u32, u32> = HashMap::new();
    fibs.insert(0, 1);
    fibs.insert(1, 1);
    let mut n = 1;
    let mut sum = 0;
    while fib(n, &mut fibs) < 4000000 {
        sum += if fib(n, &mut fibs) % 2 == 0 {
            fib(n, &mut fibs)
        } else {
            0
        };
        n += 1;
    }
    println!("{}", sum);
}

fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {
    if !fibs.contains_key(&n) {
        fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
    }
    *fibs.get(&n).unwrap()
}

error[E0596]: cannot borrow `fibs` as mutable, as it is not declared as mutable
  --> src/main.rs:22:35
   |
20 | fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {
   |                ---- help: consider changing this to be mutable: `mut fibs`
21 |     if !fibs.contains_key(&n) {
22 |         fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
   |                                   ^^^^^^^^^ cannot borrow as mutable

error[E0499]: cannot borrow `fibs` as mutable more than once at a time
  --> src/main.rs:22:35
   |
22 |         fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
   |         ---- ------               ^^^^^^^^^ second mutable borrow occurs here
   |         |    |
   |         |    first borrow later used by call
   |         first mutable borrow occurs here

error[E0596]: cannot borrow `fibs` as mutable, as it is not declared as mutable
  --> src/main.rs:22:59
   |
20 | fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {
   |                ---- help: consider changing this to be mutable: `mut fibs`
21 |     if !fibs.contains_key(&n) {
22 |         fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
   |                                                           ^^^^^^^^^ cannot borrow as mutable

error[E0499]: cannot borrow `fibs` as mutable more than once at a time
  --> src/main.rs:22:59
   |
22 |         fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
   |         ---- ------ first borrow later used by call       ^^^^^^^^^ second mutable borrow occurs here
   |         |
   |         first mutable borrow occurs here

Rust 到 Python3 的转换如下所示:

The Rust to Python3 translation looks like this:

def main():
    fibs = {}
    fibs[0] = 1
    fibs[1] = 1
    n = 1
    summ = 0
    while fib(n, fibs) < 4000000:
        summ += fib(n, fibs) if fib(n, fibs) % 2 == 0 else 0
        n+=1
    print(summ)
    print(fibs)
def fib(n, fibs):
    if n not in fibs:
        fibs[n] = fib(n-1, fibs) + fib(n-2, fibs)
    return fibs[n]
main()

我知道这个特定的实现并不理想,但我只是想学习这门语言.我试图只将哈希图的引用传递给函数.在不改变解决这个问题的方法的情况下,如果可能的话,我如何使用可变的 HashMap 引用?

I understand that this particular implementation is not ideal, but I am solely trying to learn the language. I am trying to only pass a reference of the hashmap to the function. Without changing the approach to solving this problem, how can I use mutable HashMap references, if it's even possible?

推荐答案

fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {

fibs 已经 是一个可变引用.在函数中,您说 &mut fibs,它将获得对可变引用的可变引用.这没有用,并且与正确的类型不匹配.相反,直接传递 fibs.

fibs is already a mutable reference. In the function, you say &mut fibs, which would get a mutable reference to a mutable reference. That's not useful, and doesn't match the correct type. Instead, pass fibs directly.

那么你必须把两个子调用分开:

Then you have to split out the two child calls:

fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {
    if !fibs.contains_key(&n) {
        let a = fib(n - 1, fibs);
        let b = fib(n - 2, fibs);
        fibs.insert(n, a + b);
    }
    *fibs.get(&n).unwrap()
}

最后一点是借用检查器的一个限制——使用 &mut 接收器的嵌套方法调用会导致借用错误,但将它们分成单独的语句可以解决这个问题.

This last bit is a limitation of the borrow checker — nested method calls with &mut receivers result in borrowing errors, but separating them into separate statements fixes the issue.

正如delnan 指出的:

虽然对可变引用的可变引用没有用并且会造成一些混淆,但它通常不是类型错误,因为 deref 强制可以将 &mut &mut T 转换为 &mut T,至少当编译器知道 &mut T 是预期的.

While taking a mutable reference to a mutable reference is not useful and demonstrates some confusion, it is usually not a type error, since deref coercions can turn &mut &mut T into &mut T, at least when the compiler knows that &mut T is expected.

这反映在编译器错误消息所说的内容中:

This is reflected in what the compiler error messages say:

error[E0596]: cannot borrow `fibs` as mutable, as it is not declared as mutable
  --> src/main.rs:22:35
   |
20 | fn fib(n: u32, fibs: &mut HashMap<u32, u32>) -> u32 {
   |                ---- help: consider changing this to be mutable: `mut fibs`
21 |     if !fibs.contains_key(&n) {
22 |         fibs.insert(n, fib(n - 1, &mut fibs) + fib(n - 2, &mut fibs));
   |                                   ^^^^^^^^^ cannot borrow as mutable

确实,进行建议的更改可以让代码继续处理下一个错误.但是,像这样嵌套引用会使事情变得过于复杂,因此最好保持适当数量的引用.

Indeed, making the suggested change allows the code to proceed to the next error. However, having nested references like this overcomplicates things, so it's preferred to keep to the appropriate amount of references.

这篇关于如何递归传递可变引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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