
20 高级函数与闭包
•1 min read1 min•66 words66 words
函数指针
函数指针描述了函数的签名和函数的地址,使得我们可以通过函数指针调用函数
fn 被称为 函数指针(function pointer)。通过函数指针我们可以传递函数代码。(注意函数不是方法,要满足无状态,这样才是函数式编程)
函数指针类型的表示:fn关键字+函数签名
想要表示一个函数指针类型,可以像这样fn(i32) -> i32将具体的函数名替换为fn关键字即可。并且形参也无须指明。
构成的是类型而非trait,所以与闭包的trait不同
[!cite] fn构成的是类型而非trait,所以与闭包的trait不同
不同于闭包,fn 是一个类型而不是一个 trait,所以直接指定 fn 作为参数而不是声明一个带有 Fn 作为 trait 约束的泛型参数。
Summary
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32
{
f(arg) + f(arg)
}
Summary
倾向于编写使用泛型和闭包 trait 的函数,这样它就能接受函数或闭包作为参数。
闭包不是函数指针
当闭包从其作用域捕获任何值时就不允许使用函数指针fn 作为返回类型
如果希望与某些没有闭包的外部代码交互,只使用函数指针最好
C 语言的函数可以接受函数作为参数,但 C 语言没有闭包。
通过完全限定语法从函数名中返回函数指针
trait或者类型::函数名,注意这里必须使用 “高级 trait” 部分讲到的完全限定语法,因为存在多个可能的函数。
Todo
enum Status {
Value(u32),
Stop,
}
let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
返回闭包
闭包实际上是各种实现了Fn,FnMut,FnOnce的结构体的统称
它们没有一个可返回的具体类型,如何规定可以返回任何类型但要满足闭包要求呢?
Summary
// 隐式引入泛型与trait约束
fn returns_closure() -> impl Fn(i32) -> i32
{
|x| x + 1
}
// 或者显式指定
fn returns_closure<T>() -> T
where T : impl Fn(i32)->i32
{
|x| x + 1
}
如果需要保证返回的trait一样,类型也一样,使用 trait object类型吧
创建一个由返回Box<dyn Fn> 的函数定义的闭包的 Vec<T> 以便它们有相同的类型。
