函数指针实现所有三个闭包特征(
Fn,FnMut和FnOnce),因此您总是可以将函数指针作为期望闭包的函数的参数传递.最好使用泛型类型和闭包特征之一来编写函数,这样您的函数就可以接受函数或闭包.
将闭包传递给接受函数指针作为参数的函数不会编译:
fn main() {
let a = String::from("abc");
let x = || println!("{}", a);
fn wrap(c: fn() -> ()) -> () {
c()
}
wrap(x);
}
Run Code Online (Sandbox Code Playgroud)
error[E0308]: mismatched types
--> src/main.rs:10:10
|
10 | wrap(x);
| ^ expected fn pointer, found closure
|
= note: expected type `fn()`
found type `[closure@src/main.rs:4:13: 4:33 a:_]`
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?
封闭不是一种功能.
您可以将函数传递给期望闭包的函数,但没有理由反转为真.
如果您希望能够将闭包和函数作为参数传递,只需为闭包准备它.
例如:
let a = String::from("abc");
let x = || println!("x {}", a);
fn y() {
println!("y")
}
fn wrap(c: impl Fn()) {
c()
}
wrap(x); // pass a closure
wrap(y); // pass a function
Run Code Online (Sandbox Code Playgroud)
在某些情况下,您可以将闭包作为函数指针传递。这有效:
fn main() {
let x = || {
let a = String::from("abc");
println!("{}", a);
};
fn wrap(c: fn()) {
c()
}
wrap(x);
}
Run Code Online (Sandbox Code Playgroud)
重要的区别是,不允许封闭从其环境中捕获任何东西。这意味着我们必须防止String跨越封闭边界。
任何不捕获环境的闭包都可以简单地重写为匿名独立函数,然后转换为函数指针。
添加环境后,该环境将不再可转换,并且现有答案中的所有内容均适用。
请注意,声明-> ()是非惯用语,因为如果未指定,则这是默认设置。
也可以看看:
| 归档时间: |
|
| 查看次数: |
1930 次 |
| 最近记录: |