Skip to main content
20 高级函数与闭包

20 高级函数与闭包

•1 min•66 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> 以便它们有相同的类型。