是否可以在 Rust 中进行递归闭包? [英] Is it possible to make a recursive closure in Rust?

查看:76
本文介绍了是否可以在 Rust 中进行递归闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个非常简单的例子,但我将如何做类似的事情:

This is a very simple example, but how would I do something similar to:

let fact = |x: u32| {
    match x {
        0 => 1,
        _ => x * fact(x - 1),
    }
};

我知道这个特定的例子可以通过迭代轻松完成,但我想知道是否可以在 Rust 中为更复杂的事情(例如遍历树)创建一个递归函数,或者我是否需要使用我的而是自己的堆栈.

I know that this specific example can be easily done with iteration, but I'm wondering if it's possible to make a recursive function in Rust for more complicated things (such as traversing trees) or if I'm required to use my own stack instead.

推荐答案

有几种方法可以做到这一点.

There are a few ways to do this.

你可以把闭包放到一个结构体中,然后把这个结构体传递给闭包.您甚至可以在函数中定义内联结构:

You can put closures into a struct and pass this struct to the closure. You can even define structs inline in a function:

fn main() {
    struct Fact<'s> { f: &'s dyn Fn(&Fact, u32) -> u32 }
    let fact = Fact {
        f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
    };

    println!("{}", (fact.f)(&fact, 5));
}

这解决了具有无限类型(一个将自身作为参数的函数)的问题以及在编写 fact 尚未在闭包本身内部定义的问题让事实= |x|{...} 所以不能在那里引用它.

This gets around the problem of having an infinite type (a function that takes itself as an argument) and the problem that fact isn't yet defined inside the closure itself when one writes let fact = |x| {...} and so one can't refer to it there.

另一种选择是将递归函数编写为 fn 项,也可以在函数中内联定义:

Another option is to just write a recursive function as a fn item, which can also be defined inline in a function:

fn main() {
    fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }

    println!("{}", fact(5));
}

如果您不需要从环境中捕获任何内容,这可以正常工作.

This works fine if you don't need to capture anything from the environment.

另一种选择是使用 fn 项目解决方案,但明确传递您想要的参数/环境.

One more option is to use the fn item solution but explicitly pass the args/environment you want.

fn main() {
    struct FactEnv { base_case: u32 }
    fn fact(env: &FactEnv, x: u32) -> u32 {
        if x == 0 {env.base_case} else {x * fact(env, x - 1)}
    }

    let env =  FactEnv { base_case: 1 };
    println!("{}", fact(&env, 5));
}

所有这些都适用于 Rust 1.17,并且可能从 0.6 版开始就可以使用.在 fn 中定义的 fn 与在顶层定义的没有什么不同,除了它们只能在它们所在的 fn 中访问定义在里面.

All of these work with Rust 1.17 and have probably worked since version 0.6. The fn's defined inside fns are no different to those defined at the top level, except they are only accessible within the fn they are defined inside.

这篇关于是否可以在 Rust 中进行递归闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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