如何遍历函数向量并调用它们中的每一个? [英] How can I iterate over a vector of functions and call each of them?

查看:56
本文介绍了如何遍历函数向量并调用它们中的每一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 for 循环来迭代函数向量并在每一步执行每个函数.

I'm trying to use a for loop to iterate over a vector of functions and execute each function at each step.

fn f1(i: i32) -> i32 {
    i * 2
}

fn f2(i: i32) -> i32 {
    i * 4
}

fn main() {
    let mut arr: Vec<|i32| -> i32> = Vec::new();
    arr.push(f1);
    arr.push(f2);

    for f in arr.iter() {
        println!("{}", f(1));
    }
}

但是尝试执行 f(1) 给出了这个错误:

But the attempted execution of f(1) gives this error:

error: expected function, found '&|i32| -> i32'

我猜将函数放入向量中时,它们的类型发生了变化,不再像普通函数那样工作.有没有办法把它变回来,还是我遗漏了什么?

I guess in putting the functions in the vector their type is mutated and no longer works like a normal function. Is there a way to transform it back, or am I missing something?

推荐答案

从 Rust 1.x 开始,未装箱的闭包是该语言中唯一的闭包类型,它们不需要功能标志.此外,静态函数可以很容易地转换为未装箱的闭包.因此,从函数向量中调用函数的正确方法是:

As of Rust 1.x, unboxed closures are the only kind of closures in the language, and they don't need a feature flag. Moreover, static functions can easily be converted to unboxed closures. Therefore, the correct way to call functions from a vector of functions is:

fn f1(i: i32) -> i32 { i * 2 }

fn f2(i: i32) -> i32 { i * 4 }

fn main() {
    let arr: Vec<&dyn Fn(i32) -> i32> = vec![&f1, &f2];

    for f in &arr {
        println!("{}", (f)(1));
    }
}

我使用了 Fn() 闭包,它可以通过共享引用访问它们的环境,因此通过引用迭代向量就足够了.如果我使用了 FnMut() 闭包,我将不得不通过可变引用使用迭代:

I've used Fn() closures which can access their environment through a shared reference, so it is sufficient to iterate the vector by reference. If I had used a FnMut() closure, I would have had to use iteration by mutable reference:

fn f1(i: i32) -> i32 { i * 2 }

fn f2(i: i32) -> i32 { i * 4 }

fn main() {
    let p1 = &mut f1;
    let p2 = &mut f2;

    let mut arr: Vec<&mut dyn FnMut(i32) -> i32> = vec![p1, p2];

    for f in &mut arr {
        println!("{}", (f)(1));
    }
}

类似的想法适用于 FnOnce() 和按值迭代,尽管这里我们需要使用 Box 来拥有闭包:

A similar idea holds for FnOnce() and iteration by value, although here we need to use Box to own the closure:

fn f1(i: i32) -> i32 { i * 2 }

fn f2(i: i32) -> i32 { i * 4 }

fn main() {
    let arr: Vec<Box<dyn FnOnce(i32) -> i32>> = vec![Box::new(f1), Box::new(f1)];

    for f in arr {
        println!("{}", (f)(1));
    }
}

或者,如果您知道自己只使用静态函数,则可以直接存储指向它们的指针,而无需使用闭包特征:

Alternatively, if you know that you only work with static functions, it is possible to store pointers to them directly, without using closure traits:

fn f1(i: i32) -> i32 { i * 2 }

fn f2(i: i32) -> i32 { i * 4 }

fn main() {
    let arr: Vec<fn(i32) -> i32> = vec![f1, f2];

    for f in &arr {
        println!("{}", (f)(1));
    }
}

虽然 f1f2 实际上有不同的不兼容类型,但它们会被自动强制转换为通用函数指针类型 fn(i32) ->i32 在适当的上下文中使用时,如上面的示例.

While f1 and f2 actually have different incompatible types, they are automatically coerced to the general function pointer type fn(i32) -> i32 when used in appropriate context, like in the example above.

因为静态函数没有任何环境,你可以自由地克隆对它们的引用,并通过任何类型的引用调用它们.如果您只需要静态函数,这可能是的方法.

Because static functions don't have any environment, you can freely clone references to them and call them through any kind of reference. This is probably the way to go if you only need static functions.

此答案已针对 Rust 1.x 更新;旧版本的答案保留在编辑历史记录中.

这篇关于如何遍历函数向量并调用它们中的每一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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