Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修正了对于move关键字闭包借用变量的描述;添加了3种Fn特征的承接文字 #1408

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/advance/functional-programing/closure.md
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ fn exec<'a, F: Fn(String) -> ()>(f: F) {

#### move 和 Fn

在上面,我们讲到了 `move` 关键字对于 `FnOnce` 特征的重要性,但是实际上使用了 `move` 的闭包依然可能实现了 `Fn` 或 `FnMut` 特征。
在上面,我们讲到了 `move` 关键字对于 `FnOnce` 特征的重要性,但是实际上使用了 `move` 的闭包依然可以使用 `Fn` 或 `FnMut` 特征。

因为,**一个闭包实现了哪种 Fn 特征取决于该闭包如何使用被捕获的变量,而不是取决于闭包如何捕获它们**。`move` 本身强调的就是后者,闭包如何捕获变量:

Expand All @@ -609,9 +609,9 @@ fn exec<F: FnOnce()>(f: F) {
}
```

我们在上面的闭包中使用了 `move` 关键字,所以我们的闭包捕获了它,但是由于闭包对 `s` 的使用仅仅是不可变借用,因此该闭包实际上**还**实现了 `Fn` 特征
我们在上面的闭包中使用了 `move` 关键字,所以我们的闭包捕获了它,但是由于闭包获取了 `s` 的所有权,因此该闭包实现了 `FnOnce` 的特征

细心的读者肯定发现我在上段中使用了一个 `还` 字,这是什么意思呢?因为该闭包不仅仅实现了 `FnOnce` 特征,还实现了 `Fn` 特征,将代码修改成下面这样,依然可以编译:
但是假如我们将代码修改成下面这样,依然可以编译:

```rust
fn main() {
Expand All @@ -627,6 +627,8 @@ fn exec<F: Fn()>(f: F) {
}
```

奇怪, 明明是闭包实现的是 `FnOnce` 的特征, 为什么编译器居然允许 `Fn` 特征通过编译呢?

#### 三种 Fn 的关系

实际上,一个闭包并不仅仅实现某一种 `Fn` 特征,规则如下:
Expand Down