函数指针

通过函数指针能够将函数作为参数传递给另一个函数。 函数指针的类型为小写的fn,避免与闭包的Fn混淆,用法与闭包类似:

fn add_one(x: i32) -> i32 {
    x + 1
}
 
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
    f(arg) + f(arg)
}
 
fn main() {
    let answer = do_twice(add_one, 5);
 
    println!("The answer is: {}", answer);
}

fn 是一个类型而不是一个 trait,所以直接指定 fn 作为参数而不是声明一个带有 Fn 作为 trait bound 的泛型参数

函数指针实现了三个闭包trait,Fn,FnMut,FnOnce,所以期望闭包的参数也可以传递函数指针。所以更加推荐编写使用泛型和闭包trait的函数,这样闭包和函数指针都能够进行传递

如果只期望接受fn而不接受闭包,这是希望与不存在闭包的外部代码交互。比如C语言不支持闭包。

元组结构体和元组结构体枚举成员,其实被实现为返回根据参数构造的示例的函数,称为实现了闭包trait的函数指针,例如下面的调用形式:

fn main() {
    enum Status {
        Value(u32),
        Stop,
    }
 
    let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
}

Status::Value被作为构造示例的函数使用。

返回闭包

闭包是trait,是不能直接返回的。因为它们没有可返回的具体类型,Rust 并不知道需要多少空间来储存闭包

通过如下的方式解决:

fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}