recursion - 带外部变量的递归函数

标签 recursion rust scoping

我在变量范围方面遇到了一些困难。我目前有类似这样的代码:

use std::collections::HashMap;

fn main() {
    let mut cache: HashMap<usize, usize> = HashMap::new();

    fn fib(n: usize) -> usize {
        // Special values
        if n == 0 || n == 1 {
            return 1;
        }

        // Check if value is in cache
        if let Some(&a) = cache.get(&n) {
            return a;
        }

        // Calculate
        let f = fib(n - 2) + fib(n - 1);

        // Insert in cache for later use
        cache.insert(n, f);

        return f;
    }

    println!("The 11th Fibonacci number is: {}", fib(10));
}

我想生成斐波那契数,但也使用缓存来跳过重新计算相同的项目。实际代码做了一些较繁重的计算,但也使用了递归。

但是,尝试编译它时,我得到 can't capture dynamic environment in a fn item; use the || { ... } closure form instead警告 cache.getcache.insert 。将此闭包形式应用于该代码:

use std::collections::HashMap;

fn main() {
    let mut cache: HashMap<usize, usize> = HashMap::new();

    let fib = |n: usize| -> usize {
        // Special values
        if n == 0 || n == 1 {
            return 1;
        }

        // Check if value is in cache
        if let Some(&a) = cache.get(&n) {
            return a;
        }

        // Calculate
        let f = fib(n - 2) + fib(n - 1);

        // Insert in cache for later use
        cache.insert(n, f);

        return f;
    };

    println!("The 11th Fibonacci number is: {}", fib(10));
}

修复了 cache错误,但给出 cannot find function `fib` in this scope警告 let f = ... .

我还尝试使用 Is it possible to make a recursive closure in Rust? 中所述的环境,但这并不像我调用同一个函数两次,因此在环境中有可变缓存的情况下借用环境两次。

我该如何处理这个奇怪的案例?

最佳答案

您在使用环境方面走在正确的轨道上,但您需要确保所有需要可变的东西都是可变的:

use std::collections::HashMap;

fn main() {
    struct FibEnv { cache: HashMap<usize, usize> }

    fn fib(mut env: &mut FibEnv, n: usize) -> usize {
        // Special values
        if n == 0 || n == 1 {
            return 1;
        }

        // Check if value is in cache
        if let Some(&a) = env.cache.get(&n) {
            return a;
        }

        // Calculate
        let f = fib(&mut env, n - 2) + fib(&mut env, n - 1);

        // Insert in cache for later use
        env.cache.insert(n, f);

        return f;
    }

    let cache: HashMap<usize, usize> = HashMap::new();
    let mut env = FibEnv { cache: cache };
    println!("The 11th Fibonacci number is: {}", fib(&mut env, 10));
}

正如@Shepmaster 在评论中所说,以下内容更加简单:

use std::collections::HashMap;

fn main() {
    fn fib(cache: &mut HashMap<usize, usize>, n: usize) -> usize {
        // Special values
        if n == 0 || n == 1 {
            return 1;
        }

        // Check if value is in cache
        if let Some(&a) = cache.get(&n) {
            return a;
        }

        // Calculate
        let f = fib(cache, n - 2) + fib(cache, n - 1);

        // Insert in cache for later use
        cache.insert(n, f);

        return f;
    }

    let mut cache: HashMap<usize, usize> = HashMap::new();
    println!("The 11th Fibonacci number is: {}", fib(&mut cache, 10));
}

关于recursion - 带外部变量的递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42308720/

相关文章:

java - 递归:如何尝试整数 1 到 9 的不同组合,以及(部分)反向序列以在出错时重新开始?

java - 返回数组总和的 toString 方法和递归方法中的错误

rust - Rust 如何将链表推到前面?

rust - 从功能获得的mod中获取结构

c - 如何在不泄漏内存的情况下将 Rust 结构和方法实现为 C 中的 Vec?

powershell - 无法创建 Powershell 别名

php - 使用 PHP 将大型递归函数保持在最低限度

java - 使函数中的逻辑递归

javascript - 理解这段代码的方式。它是如何工作的?

c++ - 如果返回,lambda 会超出范围吗