Merge remote-tracking branch 'upstream/master'

This commit is contained in:
spartucus 2019-01-23 16:40:22 +08:00
commit 91b1500c2a
4 changed files with 35 additions and 8 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.md linguist-detectable=true

View File

@ -2,7 +2,7 @@
> [ch07-01-mod-and-the-filesystem.md](https://github.com/rust-lang/book/blob/master/src/ch07-02-modules-and-use-to-control-scope-and-privacy.md)
> <br>
> commit 820ac357f6cf0e866e5a8e7a9c57dd3e17e9f8ca
> commit 9d431b25ca6c7200eafe4107eb0765c088923027
Rust 的此部分功能通常被引用为 “模块系统”“the module system”不过其包括了一些除模块之外的功能。在本部分我们会讨论
@ -68,10 +68,10 @@ fn main() {
```text
crate
└── sound
── instrument
└── woodwind
└── voice
└── sound
── instrument
└── woodwind
└── voice
```
<span class="caption">示例 7-3: 示例 7-2 中代码的模块树</span>
@ -270,7 +270,7 @@ mod sound {
}
fn breathe_in() {
// Function body code goes here
// 函数体
}
}
```
@ -369,6 +369,32 @@ fn main() {
<span class="caption">示例 7-13: 使用 `use` 将模块引入作用域并使用绝对路径来缩短在模块中调用项所必须的路径</span>
在作用域中增加 `use` 和路径类似于在文件系统中创建软连接符号连接symbolic link。通过在 crate 根增加 `use crate::sound::instrument`,现在 `instrument` 在作用域中就是有效的名称了,如同它被定义于 crate 根一样。现在,既可以使用老的全路径方式取得 `instrument` 模块的项,也可以使用新的通过 `use` 创建的更短的路径。通过 `use` 引入作用域的路径也会检查私有性,同其它路径一样。
如果希望通过 `use` 和相对路径来将项引入作用域,则与直接通过相对路径调用项有些小的区别:不同于从当前作用域的名称开始,`use` 中的路径必须以 `self` 示例 7-14 展示了如何指定相对路径来取得与示例 7-13 中使用绝对路径一样的行为。
<span class="filename">文件名: src/main.rs</span>
```rust
mod sound {
pub mod instrument {
pub fn clarinet() {
// 函数体
}
}
}
use self::sound::instrument;
fn main() {
instrument::clarinet();
instrument::clarinet();
instrument::clarinet();
}
```
<span class="caption">示例 7-14: 通过 `use` 和相对路径将模块引入作用域</span>
当指定 `use` 后以 `self` 开头的相对路径在未来可能不是必须的;这是一个开发者正在尽力消除的语言中的不一致。
如果调用项目的代码移动到模块树的不同位置但是定义项目的代码却没有,那么选择使用 `use` 指定绝对路径可以使更新更轻松,这与示例 7-10 中同时移动的情况相对。例如,如果我们决定采用示例 7-13 的代码,将 `main` 函数的行为提取到函数 `clarinet_trio` 中,并将该函数移动到模块 `performance_group` 中,这时 `use` 所指定的路径无需变化,如示例 7-15 所示。

View File

@ -170,6 +170,6 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
回忆 `search` 函数的目的是返回所有 `contents` 中包含 `query` 的行。类似于示例 13-19 中的 `filter` 例子,可以使用 `filter` 适配器只保留 `line.contains(query)` 返回 `true` 的那些行。接着使用 `collect` 将匹配行收集到另一个 vector 中。这样就容易多了!尝试对 `search_case_insensitive` 函数做出同样的使用迭代器方法的修改吧。
接下来的逻辑问题就是在代码中应该选择哪种风格:是使用示例 13-28 中的原始实现还是使用示例 13-29 中使用迭代器的版本?大部分 Rust 程序员倾向于使用迭代器风格。开始这有点难以理解,不过一旦你对不同迭代器的工作方式有了感觉之后,迭代器可能会更容易理解。相比摆弄不同的循环并创建新 vector迭代器代码则更关注循环的目的。这抽象出了那些老生常谈的代码,这样就更容易看清代码所特有的概念,比如迭代器中每个元素必须面对的过滤条件。
接下来的逻辑问题就是在代码中应该选择哪种风格:是使用示例 13-28 中的原始实现还是使用示例 13-29 中使用迭代器的版本?大部分 Rust 程序员倾向于使用迭代器风格。开始这有点难以理解,不过一旦你对不同迭代器的工作方式有了感觉之后,迭代器可能会更容易理解。相比摆弄不同的循环并创建新 vector迭代器代码则更关注循环的目的。这抽象那些老生常谈的代码,这样就更容易看清代码所特有的概念,比如迭代器中每个元素必须面对的过滤条件。
不过这两种实现真的完全等同吗?直觉上的假设是更底层的循环会更快一些。让我们聊聊性能吧。

View File

@ -90,7 +90,7 @@ fn main() {
需要使用 `use` 语句将 `Rc<T>` 引入作用域因为它不在 prelude 中。在 `main` 中创建了存放 5 和 10 的列表并将其存放在 `a` 的新的 `Rc<List>` 中。接着当创建 `b``c` 时,调用 `Rc::clone` 函数并传递 `a``Rc<List>` 的引用作为参数。
也可以调用 `a.clone()` 而不是 `Rc::clone(&a)`,不过在这里 Rust 的习惯是使用 `Rc::clone`。`Rc::clone` 的实现并不像大部分类型的 `clone` 实现那样对所有数据进行深拷贝。`Rc::clone` 只会增加引用计数,这并不会花费多少时间。深拷贝可能会花费很长时间。通过使用 `Rc::clone` 进行引用计数,可以明显的区别深拷贝类的克隆和增加引用计数类的克隆。当查找代码中的性能问题时,只需考虑神拷贝类克隆而无需考虑 `Rc::clone` 调用。
也可以调用 `a.clone()` 而不是 `Rc::clone(&a)`,不过在这里 Rust 的习惯是使用 `Rc::clone`。`Rc::clone` 的实现并不像大部分类型的 `clone` 实现那样对所有数据进行深拷贝。`Rc::clone` 只会增加引用计数,这并不会花费多少时间。深拷贝可能会花费很长时间。通过使用 `Rc::clone` 进行引用计数,可以明显的区别深拷贝类的克隆和增加引用计数类的克隆。当查找代码中的性能问题时,只需考虑深拷贝类的克隆而无需考虑 `Rc::clone` 调用。
### 克隆 `Rc<T>` 会增加引用计数