写点什么

5 分钟速读之 Rust 权威指南(四十二)高级函数

用户头像
码生笔谈
关注
发布于: 53 分钟前
5分钟速读之Rust权威指南(四十二)高级函数

最近几节我们都在聊一些高级特性,这一节来看函数之前没提到过的一些特性:函数指针、高阶函数

函数指针

在讲到闭包时候,我们将闭包可以作为函数参数传递,其实函数也可以作为参数,在参数位置使用fn来描述函数类型:


fn add(a: i32, b: i32) -> i32 {  a + b}
// 使用fn类型来描述函数type Adder = fn(i32, i32) -> i32;
// 描述参数类型fn run(f1: Adder, f2: Adder) -> i32 { f1(1, 2) + f2(3, 4)}
// 将add函数的指针传入run函数println!("{}", run(add, add));// 10
复制代码


函数指针和闭包trait都可以兼容闭包和普通函数,看下面这个复杂的例子:


// 函数fn sub(a: i32, b: i32) -> i32 {  a - b}
// 闭包let add = |a: i32, b: i32| -> i32 { a - b};
// f1是闭包trait,f2是函数指针fn run(f1: impl Fn(i32, i32) -> i32, f2: fn(i32, i32) -> i32) -> i32 { f1(1, 2) + f2(3, 4)}
// f1是函数指针,f2是闭包traitfn run2(f1: fn(i32, i32) -> i32, f2: impl Fn(i32, i32) -> i32) -> i32 { f1(1, 2) + f2(3, 4)}
println!("{}", run(add, sub)); // -2println!("{}", run2(add, sub)); // -2
复制代码


下面是一个既可以使用闭包也可以使用命名函数的更具体的例子:


// 使用闭包的情况:let list_nums = vec![1, 2, 3];let list_str: Vec<String> = list_nums  .iter()  .map(|n| n.to_string())  .collect();
println!("{:?}", list_str);// ["1", "2", "3"]
// 使用函数的情况:let list_str: Vec<String> = list_nums .iter() // 这里可以思考一下,ToString是一个trait,这里使用了前面“高级trait”一节中提到的完全限定语法 .map(ToString::to_string) .collect();
println!("{:?}", list_str);// ["1", "2", "3"]
复制代码


枚举也可以作为函数:


#[derive(Debug)]enum Status {  Value(u32),  Stop,}let list_status: Vec<Status> = (1..=3).map(Status::Value)  .collect();println!("{:?}", list_status);// [Value(1), Value(2), Value(3)]
复制代码


这里是一个高阶函数,将函数作为参数,返回一个闭包:


fn add(f: fn(i32) -> i32) -> impl Fn(i32) -> i32 {  // 这里需要move的原因在于借用检查器会认为当add执行完成后f会销毁,  // 而返回的闭包生命周期比较长,这里闭包用使用了add函数中的引用  // 所以需要把f的所有权转移到闭包中用来让借用检查器检查通过  return move |p: i32| {    return f(p) + 1  }}
fn add_one(x: i32) -> i32 { x + 1}
let run = add(add_one);println!("{}", run(1));
复制代码


还有种有意思的操作就是使用Box<T>来返回闭包:


fn return_closure() -> Box<dyn Fn(i32) -> i32> {  Box::new(|x| x + 1)}// 将闭包从Box中解引用获取,然后执行let x = (*return_closure())(1);println!("{}", x);// 2
复制代码


封面图:跟着Tina画美国


关注「码生笔谈」公众号,阅读更多最新章节

发布于: 53 分钟前阅读数: 2
用户头像

码生笔谈

关注

欢迎关注「码生笔谈」公众号 2018.09.09 加入

既不陪卷也不躺平,更多支楞资料,关注「码生笔谈」公众号

评论

发布
暂无评论
5分钟速读之Rust权威指南(四十二)高级函数