参考章节《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
参数并返回 i32
的 fn
因此,在 main
函数中,我们可以传递一个满足这个函数签名的函数 do_twice(add_one, 5);
本例是 add_one
使用闭包作为参数的函数也可以传递函数指针
函数指针实现了所有三个闭包 trait
(Fn
、FnMut
和 FnOnce
),所以总是可以在调用期望闭包的函数时传递函数指针作为参数。
返回闭包
闭包表现为 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)
}
|
总结一下
- 函数指针使用
fn
关键字
- 使用闭包作为参数的函数也可以传递函数指针
- 不能直接返回闭包,因为他们没有一个可返回的具体类型,可以返回一个
Box<T>
类型的方式来返回闭包