简体   繁体   English

如何将 Rust 函数作为参数传递?

[英]How do you pass a Rust function as a parameter?

Can I pass a function as a parameter?我可以将函数作为参数传递吗? If not, what is a good alternative?如果没有,有什么好的选择?

I tried some different syntaxes but I have not found the right one.我尝试了一些不同的语法,但没有找到正确的语法。 I know I can do this:我知道我可以这样做:

fn example() {
    let fun: fn(value: i32) -> i32;
    fun = fun_test;
    fun(5i32);
}

fn fun_test(value: i32) -> i32 {
    println!("{}", value);
    value
}

but that's not passing the function as a parameter to another function:但这并没有将该函数作为参数传递给另一个函数:

fn fun_test(value: i32, (some_function_prototype)) -> i32 {
    println!("{}", value);
    value
}

Sure you can:当然你可以:

fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
    println!("{}", f(value));
    value
}

fn times2(value: i32) -> i32 {
    2 * value
}

fn main() {
    fun_test(5, &times2);
}

As this is Rust, you have to take into account the ownership and lifetime of the closure .由于这是 Rust,您必须考虑闭包所有权和生命周期

TL;DR; TL; 博士; Basically there are 3 types of closures (callable objects):基本上有 3 种类型的闭包(可调用对象):

  1. Fn : It cannot modify the objects it captures. Fn :它不能修改它捕获的对象。
  2. FnMut : It can modify the objects it captures. FnMut :它可以修改它捕获的对象。
  3. FnOnce : The most restricted. FnOnce :最受限制的。 Can only be called once because when it is called it consumes itself and its captures.只能被调用一次,因为当它被调用时,它会消耗自己和它的捕获。

See When does a closure implement Fn, FnMut and FnOnce?请参阅闭包何时实现 Fn、FnMut 和 FnOnce? for more details了解更多详情

If you are using a simple pointer-to-function like closure, then the capture set is empty and you have the Fn flavor.如果您使用的是像闭包这样的简单的函数指针,那么捕获集是空的,并且您具有Fn风格。

If you want to do more fancy stuff, then you will have to use lambda functions.如果你想做更多奇特的事情,那么你将不得不使用 lambda 函数。

In Rust there are proper pointers to functions, that work just like those in C. Their type is for example fn(i32) -> i32 .在 Rust 中有正确的函数指针,就像在 C 中一样。它们的类型是例如fn(i32) -> i32 The Fn(i32) -> i32 , FnMut(i32) -> i32 and FnOnce(i32) -> i32 are actually traits. Fn(i32) -> i32FnMut(i32) -> i32FnOnce(i32) -> i32实际上是特征。 A pointer to a function always implements all three of these, but Rust also has closures, that may or may not be converted to pointers (depending on whether the capture set is empty) to functions but they do implement some of these traits.指向函数的指针总是实现所有这三个,但 Rust 也有闭包,它可能会或可能不会转换为指向函数的指针(取决于捕获集是否为空),但它们确实实现了其中一些特征。

So for example, the example from above can be expanded:例如,上面的例子可以扩展:

fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
    println!("{}", f(value));
    value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
    println!("{}", f(value));
    value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
    println!("{}", f(value));
    value
}

fn times2(value: i32) -> i32 {
    2 * value
}

fn main() {
    let y = 2;
    //static dispatch
    fun_test_impl(5, times2);
    fun_test_impl(5, |x| 2*x);
    fun_test_impl(5, |x| y*x);
    //dynamic dispatch
    fun_test_dyn(5, &times2);
    fun_test_dyn(5, &|x| 2*x);
    fun_test_dyn(5, &|x| y*x);
    //C-like pointer to function
    fun_test_ptr(5, times2);
    fun_test_ptr(5, |x| 2*x); //ok: empty capture set
    fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}

Fn , FnMut and FnOnce , outlined in the other answer, are closure types. FnFnMutFnOnce在另一个答案中概述,是闭包类型。 The types of functions that close over their scope.关闭其作用域的函数类型。

Apart from passing closures Rust also supports passing simple (non-closure) functions, like this:除了传递闭包之外,Rust 还支持传递简单(非闭包)函数,如下所示:

fn times2(value: i32) -> i32 {
    2 * value
}

fn fun_test(value: i32, f: fn(i32) -> i32) -> i32 {
    println!("{}", f (value));
    value
}

fn main() {
    fun_test (2, times2);
}

fn(i32) -> i32 here is a function pointer type . fn(i32) -> i32这里是一个函数指针类型

If you don't need a full-fledged closure than working with function types is often simpler as it doesn't have to deal with those closure lifetime nicities.如果你不需要一个成熟的闭包,那么使用函数类型通常更简单,因为它不必处理那些闭包生命周期的细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM