如何递归传递可变引用?

时间:2016-06-26 03:17:35

标签: pointers rust

我正在尝试解决Rust中的this problem

这是我的非编译Rust代码:

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

Rust to Python3的翻译如下所示:

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的引用传递给函数。如果不改变解决这个问题的方法,如果可能的话,如何使用可变的HashMap引用呢?

1 个答案:

答案 0 :(得分:1)

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

fibs 已经一个可变引用。在函数中,您说&mut fib,它将获得对可变引用的可变引用。这没用,并且与正确的类型不匹配。

然后你必须分出两个孩子的电话:

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

最后一点是借用检查器的限制hopefully be resolved by MIR。目前,使用&mut接收器的嵌套方法调用会导致借用错误,但将它们分成单独的语句可以解决问题。

作为delnan points out

  

虽然对可变引用进行可变引用是没有用的并且表现出一些混淆,但它通常不是类型错误,因为deref强制可以将&mut &mut T转换为&mut T,至少在编译时知道&mut T是预期的。

这反映在编译器错误消息中:

error: cannot borrow immutable argument `fibs` as mutable
        fibs.insert(n, fib(n-1, &mut fibs)+fib(n-2, &mut fibs));
                                     ^~~~
help: to make the argument mutable, use `mut` as shown:
fn fib(n:u32, mut fibs: &mut HashMap<u32, u32>) -> u32 {

确实,进行此更改允许代码继续执行下一个错误。但是,如果嵌套这样的引用过于复杂化,那么最好保留适当数量的引用。