<The Rust Programming Language> 配套视频(第13章-第14章)

内容来自杨旭老师 Rust编程语言入门教程(Rust语言/Rust权威指南配套)【已完结】



第13章 函数式语言特性:迭代器与闭包

闭包:能够捕获环境的匿名函数

使用闭包来创建抽象化的程序行为

闭包的类型推断和类型标注

使用泛型参数和Fn trait来存储闭包

Cacher实现的局限性

使用闭包捕获上下文环境

使用迭代器处理元素序列

Iterator trait和next方法

消耗迭代器的方法

生成其他迭代器的方法

使用闭包捕获环境

使用Iterator trait来创建自定义迭代器

改进I/O项目

使用迭代器代替clone

使用迭代器适配器让代码更加清晰

比较循环和迭代器的性能



第14章 进一步认识Cargo及crates.io

使用发布配置来定制构建

将包发布到crates.io上

编写有用的文档注释

使用pub use来导出合适的公共API

创建crates.io账户

为包添加元数据

发布到crates.io

发布已有包的新版本

使用cargo yank命令从cargo.io上移除版本

Cargo工作空间

创建工作空间

在工作空间中创建第二个包

使用cargo install从crates.io上安装可执行程序

使用自定义命令扩展Cargo的功能


当random=3时,不需要调用…还是有浪费

—分割线—

标准库中提供了一系列Fn Trait

rust中fn,fnmut,fnonce都是什么?有何作用和差异?

在Rust中,fn、fnmut 和 fnonce都是函数指针,它们之间的主要区别是:

  1. fn

这是不可变的函数指针(immutable function pointer),指向一个不可变的函数。

1
let f: fn(i32) -> i32 = |x| x + 1;
  1. fnmut

这是可变的函数指针(mutable function pointer),指向一个可变的函数。

1
let mut f: fnmut(i32) -> i32 = |x| x + 1;
  1. fnonce

这是一次性的函数指针(one-time function pointer),调用后就会被清除。

1
let f: fnonce(i32) -> i32 = |x| x + 1;

它们的主要区别和使用场景是:

  • fn: 当函数无需修改时使用,多数常规函数使用它。

  • fnmut: 当需要通过函数指针修改函数时使用,如实现 traits 时。

  • fnonce: 当函数仅需要调用一次就能完成其作用时使用,以实现一些零成本抽象。

另外,fnmut 和 fnonce 都比 fn 的函数指针有更多的限制。

总结:

  • fn: 不可变函数指针
  • fnmut: 可变函数指针
  • fnonce: 一次性函数指针

根据函数的修改需求选择合适的函数指针。


fn、fnmut和fnonce这些函数指针在Rust中的具体应用场景是什么?

fn、fnmut和fnonce这些函数指针在Rust中的常见应用场景包括:

  1. 作为函数参数传递函数
1
2
3
4
5
6
7
8
9
10
11
12
fn apply(f: fn(i32) -> i32, x: i32) -> i32 {
f(x)
}

fn inc(x: i32) -> i32 {
x + 1
}

fn main() {
let y = apply(inc, 10); // 使用fn传入不可变函数
println!("{}", y);
}
  1. 实现trait对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
trait Foo {
fn foo(&self, x: i32) -> i32;
}

struct Bar;

impl Foo for Bar {
fn foo(&self, x: i32) -> i32 {
x + 1
}
}

let mut obj = Bar as Box<dyn Foo>;

obj = Box::new(|x| x + 2); // 使用fnmut实现trait对象
  1. 闭包只需要调用一次
1
2
3
let print = |x| println!("{}", x); // 使用fnonce表示只调用一次的闭包

print("hello");
  1. 作為返回值返回函数
1
2
3
fn create_func() -> fn(i32) -> i32 {
|x| x + 1 // 返回一个fn
}

总结:

  • 作为函数参数和返回值
  • 实现trait对象
  • 表示一次性使用的闭包

根据需要选择合适的函数指针类型。

用的时候,直接使用value方法,而不是使用value字段

—分割线—

想揪其原理还是很复杂的,只需要记住这三句话

(其实,实现了Fn的都实现了FnMut,实现了FnMut的都实现了FnOnce)


—分割线—

迭代器是惰性的,除非你调用什么消耗它们的方法

skip(1) 略过一个元素

clone 会有较大性能损耗


即全局共享一个target

cargo new add-one –lib (这是一个库crate)