Improve Ch13

This commit is contained in:
Unisko PENG 2023-04-28 11:31:39 +08:00
parent 2dc65f2cdf
commit 5aeb8672ec
2 changed files with 10 additions and 7 deletions

View File

@ -19,4 +19,5 @@ fn main() {
r.width r.width
}); });
println! ("{:#?}\n{:#?}", list, sort_operations); println! ("{:#?}\n{:#?}", list, sort_operations);
} }

View File

@ -477,7 +477,7 @@ fn main() {
*清单 13-9`sort_by_key` 下使用 `FnMut` 闭包是允许的* *清单 13-9`sort_by_key` 下使用 `FnMut` 闭包是允许的*
在定义用到闭包的函数或类型时,这个 `Fn` 特质是相当重要的。下一小节中,咱们将讨论迭代器。许多迭代器方法,都会取闭包参数,因此在继续学习时,请牢记这些闭包的细节! 在定义用到闭包的函数或类型时,`Fn` 特质是相当重要的。下一小节中,咱们将讨论迭代器。许多迭代器方法,都会取闭包参数,因此在继续学习时,请牢记这些闭包的细节!
> 注:将清单 13-8 的代码,只加入一个地址符号 `&`,而修改成下面这样,也是工作的。这就要想想是为什么了:) > 注:将清单 13-8 的代码,只加入一个地址符号 `&`,而修改成下面这样,也是工作的。这就要想想是为什么了:)
@ -557,7 +557,7 @@ pub trait Iterator {
} }
``` ```
请注意此定义使用了新语法:`type Item` 与 `Self::Item`,他们定义着此特质下的一个 *关联类型associated type*。在 19 章中,咱们将深入谈及关联类型。至于现在,咱们需要知道的全部,便是这段代码表明,实现 `Iterator` 特质需要咱们同时定义一个 `Item` 类型,而这个 `Item` 类型会在 `next` 方法返回值类型中用到。也就是说,`Item` 类型将是迭代器返回的类型。 请注意此定义使用了一些新语法:`type Item` 与 `Self::Item`,他们定义着此特质下的一个 *关联类型associated type*。在 19 章中,咱们将深入谈及关联类型。至于现在,咱们只需清楚这段代码表明,实现 `Iterator` 特质需要咱们同时定义一个 `Item` 类型,而这个 `Item` 类型会在 `next` 方法返回值类型中用到。也就是说,`Item` 类型将是迭代器返回的类型。
`Iterator` 特质只需要实现者implementors定义一个方法`next` 方法,该方法会一次返回一个封装在 `Some` 中的迭代器条目,当迭代完毕时,就会返回 `None` `Iterator` 特质只需要实现者implementors定义一个方法`next` 方法,该方法会一次返回一个封装在 `Some` 中的迭代器条目,当迭代完毕时,就会返回 `None`
@ -579,17 +579,19 @@ fn iterator_demonstration() {
} }
``` ```
*清单 13-12对迭代器上的 `next` 方法进行调用* *清单 13-12调用迭代器上的 `next` 方法*
请注意这里需要将 `v1_iter` 构造为可变的:调用某个迭代器上的 `next` 方法,会修改那个迭代器用于追踪其本身位于其关联序列何处的内部状态。也就是说,此代码 *消费consumes*或用完use up了这个迭代器。每次对 `next` 的调用,都会从这个迭代器吃掉一个条目。之所以之前在使用 `for` 循环时,未曾需要将 `v1_iter` 构造为可变,是由于那个循环占据`v1_iter` 的所有权,而在幕后将其构造为了可变。 请注意咱们需将 `v1_iter` 构造为可变:调用迭代器上的 `next` 方法,会修改迭代器用来追踪其位于序列中何处的内部状态。换句话说,这段代码 *消费consumes*或用掉use up了迭代器。每次对 `next` 的调用,都会吃掉迭代器的一个条目。在咱们使用 `for` 循环时,之所以不需要将 `v1_iter` 构造为可变,是由于那个循环取得`v1_iter` 的所有权,而在幕后将其构造为了可变。
还要注意这里从到 `next` 的调用所获取到的那些值,都是到那个矢量中值的不可变引用。`iter` 方法产生出的,是一个不可变引用的迭代器。而在打算创建一个会取得 `v1` 所有权的迭代器,并返回自有数据时,则可以调用 `into_iter` 而非 `iter`。与此类似,当需要可变引用的迭代时,那么就可以调用 `iter_mut` 而非 `iter` 还要注意咱们从 `next` 的调用获取到值,都是到矢量中值的不可变引用。`iter` 方法会产生对不可变引用的迭代器。若咱们打算创建出取得 `v1` 所有权,并返回有所有权的数据时,咱们可以调用 `into_iter` 而非 `iter`。与此类似,若咱们打算对可变引用迭代,咱们可以调用 `iter_mut` 而非 `iter`
### 消费迭代器的一些方法 ### 消费迭代器的方法
`Iterator` 特质有着带有由标准库提供了默认实现的几个方法;通过查阅 `Iterator` 特质的标准库 API 文档,就可以找到这些方法。他们中的一些,就在他们的定义中调用了这个 `next` 方法,这正是在实现这个 `Iterator` 特质时,不要求实现这个 `next` 方法的原因。 **Methods that Consume the Iterator**
`Iterator` 特质有着数个带有标准库提供的默认实现的不同方法;通过查阅 `Iterator` 特质的标准库 API 文档,咱们便可找到这些方法。他们中的一些,就在其定义中调用了 `next` 方法,而这正是咱们实现 `Iterator` 特质时,不要求实现 `next` 方法的原因。
由于调用这些调用了 `next` 方法,会耗尽迭代器,因此他们被称为 *消费适配器consuming adaptors*。一个例子便是 `sum` 方法,他会取得迭代器的所有权,并通过重复调用 `next`,遍历所有条目,由此消费该迭代器。在其遍历期间,他就会把各个条目,加到一个运行中的总和,并在遍历完成时返回这个总和。下面清单 13-13有着这个 `sum` 方法运用的测试演示: 由于调用这些调用了 `next` 方法,会耗尽迭代器,因此他们被称为 *消费适配器consuming adaptors*。一个例子便是 `sum` 方法,他会取得迭代器的所有权,并通过重复调用 `next`,遍历所有条目,由此消费该迭代器。在其遍历期间,他就会把各个条目,加到一个运行中的总和,并在遍历完成时返回这个总和。下面清单 13-13有着这个 `sum` 方法运用的测试演示: