Rust 学习笔记(42)-高级函数

参考章节《Rust程序设计语言》第19.4章 高级函数

函数指针

C/C++系列的语言中,函数指针是一个很常见的概念,通过函数指针允许我们使用函数作为另一个函数的参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
fn add_one(x: i32) -> i32 {
    x + 1
}

// 参数 f: fn(i32) -> i32 是一个接收 i32 类型参数并返回 i32 类型的 函数指针
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);
}

这段代码的关键是 f: fn(i32) -> i32 它是一个接收 i32 参数并返回 i32fn
因此,在 main 函数中,我们可以传递一个满足这个函数签名的函数 do_twice(add_one, 5); 本例是 add_one

使用闭包作为参数的函数也可以传递函数指针

函数指针实现了所有三个闭包 traitFnFnMutFnOnce),所以总是可以在调用期望闭包的函数时传递函数指针作为参数。

返回闭包

闭包表现为 trait,这意味着不能直接返回闭包,但是这不能用于闭包,因为他们没有一个可返回的具体类型

这段代码尝试直接返回闭包,但它并不能编译:

1
2
3
fn returns_closure() -> dyn Fn(i32) -> i32 {
    |x| x + 1
}

编译这段代码会打印出如下类似的报错

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ cargo build
   Compiling functions-example v0.1.0 (file:///projects/functions-example)
error[E0746]: return type cannot have an unboxed trait object
 --> src/lib.rs:1:25
  |
1 | fn returns_closure() -> dyn Fn(i32) -> i32 {
  |                         ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32`
  |
1 | fn returns_closure() -> impl Fn(i32) -> i32 {
  |                         ~~~~~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0746`.
error: could not compile `functions-example` due to previous error

我们可以使用 Box<T> 智能指针来返回一个闭包

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

总结一下

  1. 函数指针使用 fn 关键字
  2. 使用闭包作为参数的函数也可以传递函数指针
  3. 不能直接返回闭包,因为他们没有一个可返回的具体类型,可以返回一个 Box<T> 类型的方式来返回闭包
updatedupdated2025-03-012025-03-01