在 Rust 中将多个函数组合成同一类型的单个函数

问题描述 投票:0回答:1

我是 Rust 新手,我想知道解决这个基本示例的最佳方法是什么。我通过返回一个闭包来组合两个

MathLogFn
类型的函数。据我了解,需要关闭才能访问周围环境中的
math_log_fns

下面的代码可以编译,但是有没有办法重构它,使

combine_math_log_fns()
的返回类型为
MathLogFn

type MathLogFn = fn(u32, u32);

fn log_sum(n1: u32, n2: u32) {
    println!("{}", n1 + n2);
}

fn log_product(n1: u32, n2: u32) {
    println!("{}", n1 * n2);
}

fn combine_math_log_fns(math_log_fns: Vec<MathLogFn>) -> Box<dyn Fn(u32, u32)> {
    Box::new(move |n1: u32, n2: u32| {
        for mlf in &math_log_fns {
            mlf(n1, n2);
        }
    })
}

fn main() {
    let mlfs: Vec<Box<dyn Fn(u32, u32)>> = vec![
        Box::new(log_sum),
        Box::new(log_product),
        combine_math_log_fns(vec![log_sum, log_product]),
    ];
}

您尝试了什么以及您期待什么?

我尝试重构,但编译器给出错误,指出它无法访问

math_log_fns
,除非使用闭包:

fn combine_math_log_fns(math_log_fns: Vec<MathLogFn>) -> MathLogFn {
    fn combined(n1: u32, n2: u32) {
        for mlf in &math_log_fns {
            mlf(n1, n2);
        }
    }

    combined
}
rust
1个回答
0
投票

这个答案扩展了我写的评论。


type MathLogFn = fn(u32, u32);
行中,
fn(u32, u32)
是一个函数指针类型。这些指针只能指向代码,而不能指向额外的运行时数据。 closure 是不同的;它可以捕获额外的运行时数据,特别是来自其环境的变量。

  1. fn log_sum
    不从其环境中捕获任何变量,因此它可以用作函数指针
  2. fn log_product
    不从其环境中捕获任何变量,因此它可以用作函数指针
  3. fn combined
    使用环境中的
    math_log_fns
    ,因此必须将其转换为闭包

我们不知道

combine_math_log_fns
必须返回一个闭包,您可以选择:

  1. Box<dyn Fn(u32, u32)>
    无法克隆,如果添加
    Clone
    绑定,克隆效率会很低
  2. Rc<dyn Fn(u32, u32)>
    ,可高效克隆
  3. Arc<dyn Fn(u32, u32) + Send + Sync>
    ,类似于
    Rc
    ,但可在多线程上下文中使用

然后,您不妨使用您选择的类型重新定义类型别名,以获得最大的互操作性:

type MathLogFn = Box<dyn Fn(u32, u32)>;
© www.soinside.com 2019 - 2024. All rights reserved.