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

时间:2016-04-03 20:18:17

标签: rust

我是否可以将函数作为Rust中的参数传递(可能是),如果可以的话,我可以这样做。

如果你不能,这是一个很好的选择。

我尝试了一些语法,但我没有得到

我知道我可以做到这一点

..//

let fun: fn(value: i32) -> i32;
fun = funTest;
fun(5i32);

..//
fn funTest(value: i32) -> i32 {
    println!("{}", value);
    value
}

但不是将函数作为参数传递给另一个函数

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

2 个答案:

答案 0 :(得分:63)

当然可以:

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

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

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

但这是Rust,所以你必须考虑ownership and lifetime of the closure

TL; DR;基本上有3种类型的闭包(可调用对象):

  1. Fn:最通用的,它是一个纯函数。
  2. FnMut:它可以修改它捕获的对象。
  3. FnOnce:最受限制的。只能被调用一次,因为它被调用时会消耗自身及其捕获。
  4. 如果你使用像闭包那样的简单指针,那么捕获集是空的,你有Fn的味道。

    如果你想做更多花哨的东西,那么你将不得不使用lambda函数。

    更新:经过一段时间学习Rust之后,我需要强烈要求解决这个问题。

    在Rust中有适当的函数指针,它们与C中的函数一样。它们的类型例如是fn(i32) -> i32Fn(i32) -> i32FnMut(i32) -> i32FnOnce(i32) -> i32实际上是特征。显然,指向函数的指针总是实现所有这三个,但Rust也有闭包,可能会也可能不会转换为指针(取决于捕获集是否为空)到函数,但它们确实实现了这些特性。

    例如,上面的例子可以扩展(并进行样式校正):

    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
    }
    

答案 1 :(得分:12)

另一个答案中概述的

FnFnMutFnOnce闭包类型。关闭其范围的函数类型。

除了传递闭包之外,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这里是function pointer type

如果你不需要一个完整的闭包而不是使用函数类型通常更简单,因为它不必处理那些关闭生命周期的特性。