From 5184acf433e7c7fe6e5856dc3094b9e618a6cf4a Mon Sep 17 00:00:00 2001 From: sunface Date: Thu, 2 Dec 2021 13:53:25 +0800 Subject: [PATCH] add appendix --- README.md | 47 ++--- src/SUMMARY.md | 6 +- src/about-book.md | 13 ++ src/appendix/derive.md | 93 +++++++++ src/appendix/intro.md | 5 +- src/appendix/{a-keywords.md => keywords.md} | 0 src/appendix/operators.md | 198 ++++++++++++++++++++ src/appendix/rust-dev.md | 120 ++++++++++++ src/appendix/rust-version.md | 25 +++ src/basic/variable.md | 2 +- src/into-rust.md | 72 +++++-- 11 files changed, 545 insertions(+), 36 deletions(-) create mode 100644 src/appendix/derive.md rename src/appendix/{a-keywords.md => keywords.md} (100%) create mode 100644 src/appendix/operators.md create mode 100644 src/appendix/rust-dev.md create mode 100644 src/appendix/rust-version.md diff --git a/README.md b/README.md index cdac8058..a7b3faab 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,12 @@ # Rust编程指南 -做任何事情,初心和目标很重要,过程也很重要,那么这里我们就来谈谈这些,关于书,关于Rust在国内的发展。 - -## Rust学习路线 -0. 入一个社区: [Rust编程学院](#Rust社区) -1. 读一本好书: [<>](https://wayto.rs) -2. 做一些习题: [Rust Excersise](https://github.com/rustcollege/rustex) -3. 看一个项目: [Simple Redis](https://github.com/rustcollege/simple-redis) -4. 学常用算法: [Algorithms](https://github.com/rustcollege/algorithms) -5. 找优秀开源: [Awesome Rust](https://github.com/rustcollege/awesome-rust) - -## 关于本书 - - 官方书名: Rust编程指南(The Way To Rust) - 官方网址: https://wayto.rs - 修订时间: **尚未发行** - Rust版本:Rust edition 2021 +## 关于本书 + #### 书本简介 `Rust编程指南`是一本涵盖了从入门到精通各个阶段的Rust书籍,书本的章节和内容组织经过深思熟虑的设计,以符合中国用户的编程使用习惯,目的是尽量对新手更友好,同时也更方便老手的后期检索查询。 @@ -49,6 +39,28 @@ Rust的外部库层次不齐,针对这一点,我们根据功能分类推荐 2. 已经熟悉Rust想要更进一步的中级Rust程序员 3. 想要随时检索一些Rust知识和代码,对生产力有要求的Rust开发者 +#### 内容说明 + +书的目录组织结构和内容组织完全是原创,其中书籍内容部分,大部分是原创,另外一部分来源于外文资料及中文翻译书籍。 + +来源于中文翻译书籍的内容都会标明来源,在复制粘贴的同时,还进行了大量的修改,一个是增加中文翻译的准确性,还有就是提升阅读流畅度,让行文更符合中国人的阅读习惯,摆脱“机器翻译味", **所以本书的内容每句话都是经过精心构思,力求提供给大家最好的阅读体验**. + +## 开源版权说明 + +Rust编程指南是完全开源的电子书籍,但是也应该受到版权的保护,毕竟凝聚了大家多个数以百计小时的汗水、牺牲了大量陪伴家人的时间,才完成了该书。 + +因此我们选择了[No License](https://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwigkv-KtMT0AhXFdXAKHdI4BCcQFnoECAQQAw&url=https%3A%2F%2Fchoosealicense.com%2Fno-permission%2F&usg=AOvVaw3M2Q4IbdhnpJ2K71TF7SPB)作为我们的版权,这意味着读者可以随意的fork、阅读,但是不能私下修改后再分发,如果想要修改,请提RP或者加入Rust编程学院,成为正式成员。 + + +## Philosophy(设计哲学) + +书本的内容组织上遵循以下原则: +1. 内聚性: 每个章节都应该系统的阐述一整块儿独立的内容,尽量减少章节之间的耦合性 +2. 先易后难:按照初级 -> 中级 -> 高级排列内容 +3. 知识链:知识B的学习如果需要先学习知识A,则A一定在B之前出现 +4. 章节命名:当用户突然想了解某个知识点时,可以很快的定位到它所在的章节,例如想了解Arc,就应该`多线程 -> Arc`这种章节目录形式 + + ## Rust社区 与国外的Rust发展如火如荼相比,国内的近况不是特别理想。 @@ -62,13 +74,4 @@ Rust的外部库层次不齐,针对这一点,我们根据功能分类推荐 官网网址: - https://college.rs -- https://rustcollege.cn - - -## Philosophy - -书本的内容组织上遵循以下原则: -1. 内聚性: 每个章节都应该系统的阐述一整块儿独立的内容,尽量减少章节之间的耦合性 -2. 先易后难:按照初级 -> 中级 -> 高级排列内容 -3. 知识链:知识B的学习如果需要先学习知识A,则A一定在B之前出现 -4. 章节命名:当用户突然想了解某个知识点时,可以很快的定位到它所在的章节,例如想了解Arc,就应该`多线程 -> Arc`这种章节目录形式 \ No newline at end of file +- https://rustcollege.cn \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 3e71a7fc..1fe72d9f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -160,4 +160,8 @@ ## 附录 - [附录](appendix/intro.md) - - [A-关键字](appendix/a-keywords.md) \ No newline at end of file + - [A-关键字](appendix/keywords.md) + - [B-运算符与符号](appendix/operators.md) + - [C-派生特征derive](appendix/derive.md) + - [D-Rust版本发布](appendix/rust-version.md) + - [E-Rust自身开发流程](appendix/rust-dev.md) \ No newline at end of file diff --git a/src/about-book.md b/src/about-book.md index 4d2f12ac..2040b256 100644 --- a/src/about-book.md +++ b/src/about-book.md @@ -40,6 +40,18 @@ Rust的外部库层次不齐,针对这一点,我们根据功能分类推荐 2. 已经熟悉Rust想要更进一步的中级Rust程序员 3. 想要随时检索一些Rust知识和代码,对生产力有要求的Rust开发者 +#### 内容说明 + +书的目录组织结构和内容组织完全是原创,其中书籍内容部分,大部分是原创,另外一部分来源于外文资料及中文翻译书籍。 + +来源于中文翻译书籍的内容都会标明来源,在复制粘贴的同时,还进行了大量的修改,一个是增加中文翻译的准确性,还有就是提升阅读流畅度,让行文更符合中国人的阅读习惯,摆脱“机器翻译味", **所以本书的内容每句话都是经过精心构思,力求提供给大家最好的阅读体验**. + +## 版权信息 + +Rust编程指南是完全开源的电子书籍,但是也应该受到版权的保护,毕竟凝聚了大家多个数以百计小时的汗水、牺牲了大量陪伴家人的时间,才完成了该书。 + +因此我们选择了[No License](https://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwigkv-KtMT0AhXFdXAKHdI4BCcQFnoECAQQAw&url=https%3A%2F%2Fchoosealicense.com%2Fno-permission%2F&usg=AOvVaw3M2Q4IbdhnpJ2K71TF7SPB)作为我们的版权,这意味着读者可以随意的fork、阅读,但是不能私下修改后再分发,如果想要修改,请提RP或者加入Rust编程学院,成为正式成员。 + #### 书中的一些标识说明 | Ferris | 意义 | |------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| @@ -66,3 +78,4 @@ Rust的外部库层次不齐,针对这一点,我们根据功能分类推荐 后者为了未来国内备案使用 + diff --git a/src/appendix/derive.md b/src/appendix/derive.md new file mode 100644 index 00000000..e43f7017 --- /dev/null +++ b/src/appendix/derive.md @@ -0,0 +1,93 @@ +## 附录 C:可派生的 trait + +在本书的各个部分中,我们讨论了可应用于结构体和枚举定义的 `derive` 属性。`derive` 属性会在使用 `derive` 语法标记的类型上生成对应 trait 的默认实现的代码。 + +在本附录中提供了标准库中所有可以使用 `derive` 的 trait 的参考。这些部分涉及到: + +* 该 trait 将会派生什么样的操作符和方法 +* 由 `derive` 提供什么样的 trait 实现 +* 由什么来实现类型的 trait +* 是否允许实现该 trait 的条件 +* 需要 trait 操作的例子 + +如果你希望不同于 `derive` 属性所提供的行为,请查阅 [标准库文档](https://doc.rust-lang.org/std/index.html) 中每个 trait 的细节以了解如何手动实现它们。 + +标准库中定义的其它 trait 不能通过 `derive` 在类型上实现。这些 trait 不存在有意义的默认行为,所以由你负责以合理的方式实现它们。 + +一个无法被派生的 trait 的例子是为终端用户处理格式化的 `Display` 。你应该时常考虑使用合适的方法来为终端用户显示一个类型。终端用户应该看到类型的什么部分?他们会找出相关部分吗?对他们来说最相关的数据格式是什么样的?Rust 编译器没有这样的洞察力,因此无法为你提供合适的默认行为。 + +本附录所提供的可派生 trait 列表并不全面:库可以为其自己的 trait 实现 `derive`,可以使用 `derive` 的 trait 列表事实上是无限的。实现 `derive` 涉及到过程宏的应用,这在第十九章的 [“宏”][macros] 有介绍。 + +### 用于程序员输出的 `Debug` + +`Debug` trait 用于开启格式化字符串中的调试格式,其通过在 `{}` 占位符中增加 `:?` 表明。 + +`Debug` trait 允许以调试目的来打印一个类型的实例,所以使用该类型的程序员可以在程序执行的特定时间点观察其实例。 + +例如,在使用 `assert_eq!` 宏时,`Debug` trait 是必须的。如果等式断言失败,这个宏就把给定实例的值作为参数打印出来,如此程序员可以看到两个实例为什么不相等。 + +### 等值比较的 `PartialEq` 和 `Eq` + +`PartialEq` trait 可以比较一个类型的实例以检查是否相等,并开启了 `==` 和 `!=` 运算符的功能。 + +派生的 `PartialEq` 实现了 `eq` 方法。当 `PartialEq` 在结构体上派生时,只有*所有* 的字段都相等时两个实例才相等,同时只要有任何字段不相等则两个实例就不相等。当在枚举上派生时,每一个成员都和其自身相等,且和其他成员都不相等。 + +例如,当使用 `assert_eq!` 宏时,需要比较比较一个类型的两个实例是否相等,则 `PartialEq` trait 是必须的。 + +`Eq` trait 没有方法。其作用是表明每一个被标记类型的值等于其自身。`Eq` trait 只能应用于那些实现了 `PartialEq` 的类型,但并非所有实现了 `PartialEq` 的类型都可以实现 `Eq`。浮点类型就是一个例子:浮点数的实现表明两个非数字(`NaN`,not-a-number)值是互不相等的。 + +例如,对于一个 `HashMap` 中的 key 来说, `Eq` 是必须的,这样 `HashMap` 就可以知道两个 key 是否一样了。 + +### 次序比较的 `PartialOrd` 和 `Ord` + +`PartialOrd` trait 可以基于排序的目的而比较一个类型的实例。实现了 `PartialOrd` 的类型可以使用 `<`、 `>`、`<=` 和 `>=` 操作符。但只能在同时实现了 `PartialEq` 的类型上使用 `PartialOrd`。 + +派生 `PartialOrd` 实现了 `partial_cmp` 方法,其返回一个 `Option` ,但当给定值无法产生顺序时将返回 `None`。尽管大多数类型的值都可以比较,但一个无法产生顺序的例子是:浮点类型的非数字值。当在浮点数上调用 `partial_cmp` 时,`NaN` 的浮点数将返回 `None`。 + +当在结构体上派生时,`PartialOrd` 以在结构体定义中字段出现的顺序比较每个字段的值来比较两个实例。当在枚举上派生时,认为在枚举定义中声明较早的枚举变体小于其后的变体。 + +例如,对于来自于 `rand` crate 中的 `gen_range` 方法来说,当在一个大值和小值指定的范围内生成一个随机值时,`PartialOrd` trait 是必须的。 + +`Ord` trait 也让你明白在一个带注解类型上的任意两个值存在有效顺序。`Ord` trait 实现了 `cmp` 方法,它返回一个 `Ordering` 而不是 `Option`,因为总存在一个合法的顺序。只可以在实现了 `PartialOrd` 和 `Eq`(`Eq` 依赖 `PartialEq`)的类型上使用 `Ord` trait 。当在结构体或枚举上派生时, `cmp` 和以 `PartialOrd` 派生实现的 `partial_cmp` 表现一致。 + +例如,当在 `BTreeSet`(一种基于有序值存储数据的数据结构)上存值时,`Ord` 是必须的。 + +### 复制值的 `Clone` 和 `Copy` + +`Clone` trait 可以明确地创建一个值的深拷贝(deep copy),复制过程可能包含任意代码的执行以及堆上数据的复制。查阅第四章 [“变量和数据的交互方式:移动”][ways-variables-and-data-interact-clone] 以获取有关 `Clone` 的更多信息。 + +派生 `Clone` 实现了 `clone` 方法,其为整个的类型实现时,在类型的每一部分上调用了 `clone` 方法。这意味着类型中所有字段或值也必须实现了 `Clone`,这样才能够派生 `Clone` 。 + +例如,当在一个切片(slice)上调用 `to_vec` 方法时,`Clone` 是必须的。切片并不拥有其所包含实例的类型,但是从 `to_vec` 中返回的 vector 需要拥有其实例,因此,`to_vec` 在每个元素上调用 `clone`。因此,存储在切片中的类型必须实现 `Clone`。 + +`Copy` trait 允许你通过只拷贝存储在栈上的位来复制值而不需要额外的代码。查阅第四章 [“只在栈上的数据:拷贝”][stack-only-data-copy] 的部分来获取有关 `Copy` 的更多信息。 + +`Copy` trait 并未定义任何方法来阻止编程人员重写这些方法或违反不需要执行额外代码的假设。尽管如此,所有的编程人员可以假设复制(copy)一个值非常快。 + +可以在类型内部全部实现 `Copy` trait 的任意类型上派生 `Copy`。 但只可以在那些同时实现了 `Clone` 的类型上使用 `Copy` trait ,因为一个实现了 `Copy` 的类型也简单地实现了 `Clone`,其执行和 `Copy` 相同的任务。 + +`Copy` trait 很少使用;实现 `Copy` 的类型是可以优化的,这意味着你无需调用 `clone`,这让代码更简洁。 + +任何使用 `Copy` 的代码都可以通过 `Clone` 实现,但代码可能会稍慢,或者不得不在代码中的许多位置上使用 `clone`。 + +### 固定大小的值到值映射的 `Hash` + +`Hash` trait 可以实例化一个任意大小的类型,并且能够用哈希(hash)函数将该实例映射到一个固定大小的值上。派生 `Hash` 实现了 `hash` 方法。`hash` 方法的派生实现结合了在类型的每部分调用 `hash` 的结果,这意味着所有的字段或值也必须实现了 `Hash`,这样才能够派生 `Hash`。 + +例如,在 `HashMap` 上存储数据,存放 key 的时候,`Hash` 是必须的。 + +### 默认值的 `Default` + +`Default` trait 使你创建一个类型的默认值。 派生 `Default` 实现了 `default` 函数。`default` 函数的派生实现调用了类型每部分的 `default` 函数,这意味着类型中所有的字段或值也必须实现了 `Default`,这样才能够派生 `Default` 。 + +`Default::default` 函数通常结合结构体更新语法一起使用,这在第五章的 [“使用结构体更新语法从其他实例中创建实例”][creating-instances-from-other-instances-with-struct-update-syntax] 部分有讨论。可以自定义一个结构体的一小部分字段而剩余字段则使用 `..Default::default()` 设置为默认值。 + +例如,当你在 `Option` 实例上使用 `unwrap_or_default` 方法时,`Default` trait是必须的。如果 `Option` 是 `None`的话, `unwrap_or_default` 方法将返回存储在 `Option` 中 `T` 类型的 `Default::default` 的结果。 + +[creating-instances-from-other-instances-with-struct-update-syntax]: +ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax +[stack-only-data-copy]: +ch04-01-what-is-ownership.html#stack-only-data-copy +[ways-variables-and-data-interact-clone]: +ch04-01-what-is-ownership.html#ways-variables-and-data-interact-clone +[macros]: ch19-06-macros.html#macros diff --git a/src/appendix/intro.md b/src/appendix/intro.md index 56901574..31f59e4f 100644 --- a/src/appendix/intro.md +++ b/src/appendix/intro.md @@ -1,2 +1,5 @@ # 附录 -附录中包含了一些Rust常用概念的快速索引,方便你的日常查询使用 \ No newline at end of file + +附录中包含了一些Rust常用概念的快速索引,方便你的日常查询使用。 + +> 大部分的附录借鉴了Rust Book以及相应的[中文翻译书籍](https://rustwiki.org/zh-CN/book/),但同时做了一些的修改,增加准确性和阅读流畅度 \ No newline at end of file diff --git a/src/appendix/a-keywords.md b/src/appendix/keywords.md similarity index 100% rename from src/appendix/a-keywords.md rename to src/appendix/keywords.md diff --git a/src/appendix/operators.md b/src/appendix/operators.md new file mode 100644 index 00000000..c34453fe --- /dev/null +++ b/src/appendix/operators.md @@ -0,0 +1,198 @@ +## 附录 B:运算符与符号 + + +该附录包含了 Rust 目前出现过的各种符号,这些符号之前都分散在各个章节中。 + +### 运算符 + +表 B-1 包含了 Rust 中的运算符、上下文中的示例、简短解释以及该运算符是否可重载。如果一个运算符是可重载的,则该运算符上用于重载的特征也会列出。 + +下表中,`expr`是表达式,`ident`是标识符,`type`是类型,`var`是变量,`trait`是特征,`pat`是匹配分支(pattern)。 + +表 B-1: 运算符 +| 运算符 | 示例 | 解释 | 是否可重载 | +|----------|---------|-------------|---------------| +| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | 宏展开 | | +| `!` | `!expr` | 按位非或逻辑非 | `Not` | +| `!=` | `var != expr` | 不等比较 | `PartialEq` | +| `%` | `expr % expr` | 算术取模 | `Rem` | +| `%=` | `var %= expr` | 算术取模与赋值 | `RemAssign` | +| `&` | `&expr`, `&mut expr` | 借用 | | +| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | 借用指针类型 | | +| `&` | `expr & expr` | 按位与 | `BitAnd` | +| `&=` | `var &= expr` | 按位与及赋值 | `BitAndAssign` | +| `&&` | `expr && expr` | 逻辑与 | | +| `*` | `expr * expr` | 算术乘法 | `Mul` | +| `*=` | `var *= expr` | 算术乘法与赋值 | `MulAssign` | +| `*` | `*expr` | 解引用 | | +| `*` | `*const type`, `*mut type` | 原生指针 | | +| `+` | `trait + trait`, `'a + trait` | 复合类型限制 | | +| `+` | `expr + expr` | 算术加法 | `Add` | +| `+=` | `var += expr` | 算术加法与赋值 | `AddAssign` | +| `,` | `expr, expr` | 参数以及元素分隔符 | | +| `-` | `- expr` | 算术取负 | `Neg` | +| `-` | `expr - expr` | 算术减法| `Sub` | +| `-=` | `var -= expr` | 算术减法与赋值 | `SubAssign` | +| `->` | `fn(...) -> type`, |...| -> type | 函数与闭包,返回类型 | | +| `.` | `expr.ident` | 成员访问 | | +| `..` | `..`, `expr..`, `..expr`, `expr..expr` | 右半开区间 | PartialOrd | +| `..=` | `..`, `expr..`, `..expr`, `expr..expr` | 闭合区间 | PartialOrd | +| `..` | `..expr` | 结构体更新语法 | | +| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “代表剩余部分”的模式绑定 | | +| `...` | `expr...expr` | (不推荐使用,用`..=`替代) 闭合区间 | | +| `/` | `expr / expr` | 算术除法 | `Div` | +| `/=` | `var /= expr` | 算术除法与赋值 | `DivAssign` | +| `:` | `pat: type`, `ident: type` | 约束 | | +| `:` | `ident: expr` | 结构体字段初始化 | | +| `:` | `'a: loop {...}` | 循环标志 | | +| `;` | `expr;` | 语句和语句结束符 | | +| `;` | `[...; len]` | 固定大小数组语法的部分 | | +| `<<` | `expr << expr` |左移 | `Shl` | +| `<<=` | `var <<= expr` | 左移与赋值| `ShlAssign` | +| `<` | `expr < expr` | 小于比较 | `PartialOrd` | +| `<=` | `expr <= expr` | 小于等于比较 | `PartialOrd` | +| `=` | `var = expr`, `ident = type` | 赋值/等值 | | +| `==` | `expr == expr` | 等于比较 | `PartialEq` | +| `=>` | `pat => expr` | 匹配分支语法的部分 | | +| `>` | `expr > expr` | 大于比较 | `PartialOrd` | +| `>=` | `expr >= expr` | 大于等于比较 | `PartialOrd` | +| `>>` | `expr >> expr` | 右移 | `Shr` | +| `>>=` | `var >>= expr` | 右移与赋值 | `ShrAssign` | +| `@` | `ident @ pat` | 模式绑定 | | +| `^` | `expr ^ expr` | 按位异或 | `BitXor` | +| `^=` | `var ^= expr` | 按位异或与赋值 | `BitXorAssign` | +| | | pat | pat | 模式匹配中的多个可选条件 | | +| | | expr | expr | 按位或 | `BitOr` | +| |= | var |= expr | 按位或与赋值 | `BitOrAssign` | +| || | expr || expr | 逻辑或 | | +| `?` | `expr?` | 错误传播 | | + + +### 非运算符符号 + +下面的列表中包含了所有和运算符不一样功能的非字符符号;也就是说,他们并不像函数调用或方法调用一样表现。 + +表 B-2 展示了以其自身出现以及出现在合法其他各个地方的符号。 + +表 B-2:独立语法 + +| 符号 | 解释 | +|--------|-------------| +| `'ident` | 命名生命周期或循环标签 | +| `...u8`, `...i32`, `...f64`, `...usize`, 等 | 指定类型的数值常量 | +| `"..."` | 字符串常量 | +| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | 原始字符串字面值, 未处理的转义字符 | +| `b"..."` | 字节字符串字面值; 构造一个 `[u8]` 类型而非字符串 | +| `br"..."`, `br#"..."#`, `br##"..."##`, 等 | 原始字节字符串字面值,原始和字节字符串字面值的结合 | +| `'...'` | 字符字面值 | +| `b'...'` | ASCII 码字节字面值 | +| |...| expr | 闭包 | +| `!` | 离散函数的总是为空的类型 | +| `_` | “忽略” 模式绑定;也用于增强整型字面值的可读性 | + +表 B-3 展示了出现在从模块结构到项的路径上下文中的符号 + +表 B-3:路径相关语法 + +| 符号 | 解释 | +|--------|-------------| +| `ident::ident` | 命名空间路径 | +| `::path` | 与 crate 根相对的路径(如一个显式绝对路径) | +| `self::path` | 与当前模块相对的路径(如一个显式相对路径)| +| `super::path` | 与父模块相对的路径 | +| `type::ident`, `::ident` | 关联常量、函数以及类型 | +| `::...` | 不可以被直接命名的关联项类型(如 `<&T>::...`,`<[T]>::...`, 等) | +| `trait::method(...)` | 通过命名定义的 trait 来消除方法调用的二义性 | +| `type::method(...)` | 通过命名定义的类型来消除方法调用的二义性 | +| `::method(...)` | 通过命名 trait 和类型来消除方法调用的二义性 | + + +表 B-4 展示了出现在泛型类型参数上下文中的符号。 + +表 B-4:泛型 + +| 符号 | 解释 | +|--------|-------------| +| `path<...>` | 为一个类型中的泛型指定具体参数(如 `Vec`) | +| `path::<...>`, `method::<...>` | 为一个泛型、函数或表达式中的方法指定具体参数,通常指 turbofish(如 `"42".parse::()`)| +| `fn ident<...> ...` | 泛型函数定义 | +| `struct ident<...> ...` | 泛型结构体定义 | +| `enum ident<...> ...` | 泛型枚举定义 | +| `impl<...> ...` | 定义泛型实现 | +| `for<...> type` | 高级生命周期限制 | +| `type` | 泛型,其一个或多个相关类型必须被指定为特定类型(如 `Iterator`)| + +表 B-5 展示了出现在使用 trait bounds 约束泛型参数上下文中的符号。 + +表 B-5: Trait Bound 约束 + +| 符号 | 解释 | +|--------|-------------| +| `T: U` | 泛型参数 `T` 约束于实现了 `U` 的类型 | +| `T: 'a` | 泛型 `T` 的生命周期必须长于 `'a`(意味着该类型不能传递包含生命周期短于 `'a` 的任何引用)| +| `T : 'static` | 泛型 T 不包含除 'static 之外的借用引用 | +| `'b: 'a` | 泛型 `'b` 生命周期必须长于泛型 `'a` | +| `T: ?Sized` | 使用一个不定大小的泛型类型 | +| `'a + trait`, `trait + trait` | 复合类型限制 | + +表 B-6 展示了在调用或定义宏以及在其上指定属性时的上下文中出现的符号。 + +表 B-6: 宏与属性 + +| 符号 | 解释 | +|--------|-------------| +| `#[meta]` | 外部属性 | +| `#![meta]` | 内部属性 | +| `$ident` | 宏替换 | +| `$ident:kind` | 宏捕获 | +| `$(…)…` | 宏重复 | + +表 B-7 展示了写注释的符号。 + +表 B-7: 注释 + +| 符号 | 注释 | +|--------|-------------| +| `//` | 行注释 | +| `//!` | 内部行文档注释 | +| `///` | 外部行文档注释 | +| `/*...*/` | 块注释 | +| `/*!...*/` | 内部块文档注释 | +| `/**...*/` | 外部块文档注释 | + +表 B-8 展示了出现在使用元组时上下文中的符号。 + +表 B-8: 元组 + +| 符号 | 解释 | +|--------|-------------| +| `()` | 空元组(亦称单元),即是字面值也是类型 | +| `(expr)` | 括号表达式 | +| `(expr,)` | 单一元素元组表达式 | +| `(type,)` | 单一元素元组类型 | +| `(expr, ...)` | 元组表达式 | +| `(type, ...)` | 元组类型 | +| `expr(expr, ...)` | 函数调用表达式;也用于初始化元组结构体 `struct` 以及元组枚举 `enum` 变体 | +| `ident!(...)`, `ident!{...}`, `ident![...]` | 宏调用 | +| `expr.0`, `expr.1`, etc. | 元组索引 | + +表 B-9 展示了使用大括号的上下文。 + +表 B-9: 大括号 + +| 符号 | 解释 | +|---------|-------------| +| `{...}` | 块表达式 | +| `Type {...}` | `struct` 字面值 | + +表 B-10 展示了使用方括号的上下文。 + +表 B-10: 方括号 + +| 符号 | 解释 | +|---------|-------------| +| `[...]` | 数组 | +| `[expr; len]` | 复制了 `len`个 `expr`的数组 | +| `[type; len]` | 包含 `len`个 `type` 类型的数组| +| `expr[expr]` | 集合索引。 重载(`Index`, `IndexMut`) | +| `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | 集合索引,使用 `Range`,`RangeFrom`,`RangeTo` 或 `RangeFull` 作为索引来代替集合 slice | diff --git a/src/appendix/rust-dev.md b/src/appendix/rust-dev.md new file mode 100644 index 00000000..1e79d8b3 --- /dev/null +++ b/src/appendix/rust-dev.md @@ -0,0 +1,120 @@ +## 附录E Rust自身开发流程 + + +本附录介绍 Rust 是如何开发的以及这如何影响作为 Rust 开发者的你。 + +### 无停滞稳定 + +作为一个语言,Rust **十分** 注重代码的稳定性。我们希望 Rust 成为你代码坚实的基础,假如持续地有东西在变,这个希望就实现不了。但与此同时,如果不能实验新功能的话,在发布之前我们又无法发现其中重大的缺陷,而一旦发布便再也没有修改的机会了。 + +对于这个问题我们的解决方案被称为 “无停滞稳定”(“stability without stagnation”),其指导性原则是:无需担心升级到最新的稳定版 Rust。每次升级应该是无痛的,并应带来新功能,更少的 bug 和更快的编译速度。 + +### Choo, Choo! ~~(开车啦,逃)~~ 发布通道和发布时刻表(Riding the Trains) + +Rust 开发运行于一个 ~~车次表~~ **发布时刻表**(*train schedule*)之上。也就是说,所有的开发工作都位于 Rust 仓库的 `master` 分支。发布采用 software release train 模型,其被用于思科 IOS 等其它软件项目。Rust 有三个 **发布通道**(*release channel*): + +* Nightly +* Beta +* Stable(稳定版) + +大部分 Rust 开发者主要采用稳定版通道,不过希望实验新功能的开发者可能会使用 nightly 或 beta 版。 + +如下是一个开发和发布过程如何运转的例子:假设 Rust 团队正在进行 Rust 1.5 的发布工作。该版本发布于 2015 年 12 月,不过这里只是为了提供一个真实的版本。Rust 新增了一项功能:一个 `master` 分支的新提交。每天晚上,会产生一个新的 nightly 版本。每天都是发布版本的日子,而这些发布由发布基础设施自动完成。所以随着时间推移,发布轨迹看起来像这样,版本一天一发: + +```text +nightly: * - - * - - * +``` + +每 6 周时间,是准备发布新版本的时候了!Rust 仓库的 `beta` 分支会从用于 nightly 的 `master` 分支产生。现在,有了两个发布版本: + +```text +nightly: * - - * - - * + | +beta: * +``` + +大部分 Rust 用户不会主要使用 beta 版本,不过在 CI 系统中对 beta 版本进行测试能够帮助 Rust 发现可能的回归缺陷(regression)。同时,每天仍产生 nightly 发布: + +```text +nightly: * - - * - - * - - * - - * + | +beta: * +``` + +比如我们发现了一个回归缺陷。好消息是在这些缺陷流入稳定发布之前还有一些时间来测试 beta 版本!fix 被合并到 `master`,为此 nightly 版本得到了修复,接着这些 fix 将 backport 到 `beta` 分支,一个新的 beta 发布就产生了: + +```text +nightly: * - - * - - * - - * - - * - - * + | +beta: * - - - - - - - - * +``` + +第一个 beta 版的 6 周后,是发布稳定版的时候了!`stable` 分支从 `beta` 分支生成: + +```text +nightly: * - - * - - * - - * - - * - - * - * - * + | +beta: * - - - - - - - - * + | +stable: * +``` + +好的!Rust 1.5 发布了!然而,我们忘了些东西:因为又过了 6 周,我们还需发布 **新版** Rust 的 beta 版,Rust 1.6。所以从 `beta` 生成 `stable` 分支后,新版的 `beta` 分支也再次从 `nightly` 生成: + +```text +nightly: * - - * - - * - - * - - * - - * - * - * + | | +beta: * - - - - - - - - * * + | +stable: * +``` + +这被称为 “train model”,因为每 6 周,一个版本 “离开车站”(“leaves the station”),不过从 beta 通道到达稳定通道还有一段旅程。 + +Rust 每 6 周发布一个版本,如时钟般准确。如果你知道了某个 Rust 版本的发布时间,就可以知道下个版本的时间:6 周后。每 6 周发布版本的一个好的方面是下一班车会来得更快。如果特定版本碰巧缺失某个功能也无需担心:另一个版本很快就会到来!这有助于减少因临近发版时间而偷偷释出未经完善的功能的压力。 + +多亏了这个过程,你总是可以切换到下一版本的 Rust 并验证是否可以轻易的升级:如果 beta 版不能如期工作,你可以向 Rust 团队报告并在发布稳定版之前得到修复!beta 版造成的破坏是非常少见的,不过 `rustc` 也不过是一个软件,可能会存在 bug。 + +### 不稳定功能 + +这个发布模型中另一个值得注意的地方:不稳定功能(unstable features)。Rust 使用一个被称为 “功能标记”(“feature flags”)的技术来确定给定版本的某个功能是否启用。如果新功能正在积极地开发中,其提交到了 `master`,因此会出现在 nightly 版中,不过会位于一个 **功能标记** 之后。作为用户,如果你希望尝试这个正在开发的功能,则可以在源码中使用合适的标记来开启,不过必须使用 nightly 版。 + +如果使用的是 beta 或稳定版 Rust,则不能使用任何功能标记。这是在新功能被宣布为永久稳定之前获得实用价值的关键。这既满足了希望使用最尖端技术的同学,那些坚持稳定版的同学也知道其代码不会被破坏。这就是无停滞稳定。 + +本书只包含稳定的功能,因为还在开发中的功能仍可能改变,当其进入稳定版时肯定会与编写本书的时候有所不同。你可以在网上获取 nightly 版的文档。 + +### Rustup 和 Rust Nightly 的职责 + +Rustup 使得改变不同发布通道的 Rust 更为简单,其在全局或分项目的层次工作。其默认会安装稳定版 Rust。例如为了安装 nightly: + +```text +$ rustup install nightly +``` + +你会发现 `rustup` 也安装了所有的 **工具链**(*toolchains*, Rust 和其相关组件)。如下是一位作者的 Windows 计算机上的例子: + +```powershell +> rustup toolchain list +stable-x86_64-pc-windows-msvc (default) +beta-x86_64-pc-windows-msvc +nightly-x86_64-pc-windows-msvc +``` + +如你所见,默认是稳定版。大部分 Rust 用户在大部分时间使用稳定版。你可能也会这么做,不过如果你关心最新的功能,可以为特定项目使用 nightly 版。为此,可以在项目目录使用 `rustup override` 来设置当前目录 `rustup` 使用 nightly 工具链: + +```text +$ cd ~/projects/needs-nightly +$ rustup override set nightly +``` + +现在,每次在 *~/projects/needs-nightly* 调用 `rustc` 或 `cargo`,`rustup` 会确保使用 nightly 版 Rust。在你有很多 Rust 项目时大有裨益! + +### RFC 过程和团队 + +那么你如何了解这些新功能呢?Rust 开发模式遵循一个 **Request For Comments (RFC) 过程**。如果你希望改进 Rust,可以编写一个提议,也就是 RFC。 + +任何人都可以编写 RFC 来改进 Rust,同时这些 RFC 会被 Rust 团队评审和讨论,他们由很多不同分工的子团队组成。这里是 [Rust 官网上](https://www.rust-lang.org/governance) 所有团队的总列表,其包含了项目中每个领域的团队:语言设计、编译器实现、基础设施、文档等。各个团队会阅读相应的提议和评论,编写回复,并最终达成接受或回绝功能的一致。 + +如果功能被接受了,在 Rust 仓库会打开一个 issue,人们就可以实现它。实现功能的人当然可能不是最初提议功能的人!当实现完成后,其会合并到 `master` 分支并位于一个功能开关(feature gate)之后,正如 [“不稳定功能”](#unstable-features) 部分所讨论的。 + +在稍后的某个时间,一旦使用 nightly 版的 Rust 团队能够尝试这个功能了,团队成员会讨论这个功能,它如何在 nightly 中工作,并决定是否应该进入稳定版。如果决定继续推进,功能开关会移除,然后这个功能就被认为是稳定的了!乘着“发布的列车”,最终在新的稳定版 Rust 中出现。 diff --git a/src/appendix/rust-version.md b/src/appendix/rust-version.md new file mode 100644 index 00000000..ce3c0108 --- /dev/null +++ b/src/appendix/rust-version.md @@ -0,0 +1,25 @@ +## 附录 D:Rust版本 + +早在第一章,我们见过 `cargo new` 在 *Cargo.toml* 中增加了一些有关 `edition` 的元数据。本附录将解释其意义! + +与其它语言相比,Rust的更新迭代较为频繁(得益于精心设计过的发布流程以及Rust语言开发者团队管理): +- 每6周发布一个迭代版本 +- 2-3年发布一个新的大版本:Rust 2021 edtion, 每一个版本会结合已经落地的功能,并提供一个清晰的带有完整更新文档和工具的功能包。新版本会作为常规的 6 周发布过程的一部分发布。 + +好处在于,可以满足不同的用户群体的需求: +- 对于活跃的Rust用户,他们总是能很快获取到新的语言内容,毕竟,尝鲜是技术爱好者的共同特点:) +- 对于一般的用户,edition的发布会告诉这些用户:Rust语言相比上次大版本发布,有了重大的改进,值得一看 +- 对于Rust语言开发者,可以让他们的工作成果更快的被世人所知,不必锦衣夜行 + + +在本文档编写时,Rust 已经有三个版本:Rust 2015、2018、2021。本书基于 Rust 2021 edition 编写。 + +*Cargo.toml* 中的 `edition` 字段表明代码应该使用哪个版本编译。如果该字段不存在,其默认为 `2021` 以提供后向兼容性。 + +每个项目都可以选择不同于默认的 2021 edition 的版本。这样,版本可能会包含不兼容的修改,比如新增关键字可能会与代码中的标识符冲突并导致错误。不过除非选择兼容这些修改,(旧)代码仍将能够编译,即便升级了 Rust 编译器的版本。 + +所有 Rust 编译器都支持任何之前存在的编译器版本,并可以链接任何支持版本的 crate。编译器修改只影响最初的解析代码的过程。因此,如果你使用 Rust 2021 而某个依赖使用 Rust 2018,你的项目仍旧能够编译并使用该依赖。反之,若项目使用 Rust 2018 而依赖使用 Rust 2021 亦可工作。 + +有一点需要明确:大部分功能在所有版本中都能使用。开发者使用任何 Rust 版本将能继续接收最新稳定版的改进。然而在一些情况,主要是增加了新关键字的时候,则可能出现了只能用于新版本的功能。只需切换版本即可利用新版本的功能。 + +请查看 [Edition Guide](https://rust-lang-nursery.github.io/edition-guide/) 了解更多细节,这是一个完全介绍版本的书籍,包括如何通过 `cargo fix` 自动将代码迁移到新版本。 diff --git a/src/basic/variable.md b/src/basic/variable.md index 7c530ff5..0d0e4e32 100644 --- a/src/basic/variable.md +++ b/src/basic/variable.md @@ -16,7 +16,7 @@ 在命名方面,和其它语言没有区别,不过当你给变量命名时,需要遵循[Rust命名规范](../style-guide/naming.md)。 -> Rust语言有一些**关键字**(*keywords*),和其他语言一样,这些关键字都是被保留给Rust语言使用的,因此,这些关键字不能被用作变量或函数的名称。 在[附录 A](../appendix/a-keywords) 中可找到关键字列表。 +> Rust语言有一些**关键字**(*keywords*),和其他语言一样,这些关键字都是被保留给Rust语言使用的,因此,这些关键字不能被用作变量或函数的名称。 在[附录 A](../appendix/keywords) 中可找到关键字列表。 ## 变量绑定 diff --git a/src/into-rust.md b/src/into-rust.md index 3ffb8c4d..a2e4521b 100644 --- a/src/into-rust.md +++ b/src/into-rust.md @@ -1,14 +1,12 @@ # 进入Rust编程世界 -## Rust发展历程 +## 一、Rust发展历程 Rust 最早是 Mozilla 雇员 Graydon Hoare 的一个个人项目,从 2009 年开始,得到了 Mozilla 研究院的支助,2010 年项目对外公布。2010 ~2011 年间实现的自举。从此以后,Rust 经历了巨大的设计变化和反复(历程极其艰辛),终于在 2015 年 5 月 15日发布了 1.0 版。在这个研发过程中,Rust 建立了一个强大活跃的社区,形成了一整套完善稳定的项目贡献机制(Rust能够飞速发展,与这一点密不可分)。Rust 现在由 [Rust项目开发者社区](https://github.com/rust-lang/rust)维护。 大家可能疑惑Rust为啥用了这么久才到1.0版本?与之相比,Go语言2009年发布,却在2012年仅用3年就发布了1.0版本。首先是因为Rust语言特性较为复杂,因此需要全盘考虑的问题非常多;其次,Rust当时的参与者太多了,七嘴八舌的声音也很多,导致了众口难调,而Rust开发团队又非常重视社区的意见 ;最后,一旦1.0快速发布,那么后续大部分语言特性就无法再修改,对于有完美强迫症的Rust开发者团队来说,某种程度上的不完美是不可接受的。因此,Rust语言用了足足6年时间,才发布了尽善尽美的1.0版本。 - - -## 使用现状 +## 二、使用现状 一般来说,一门编程语言能在某一年成为全世界最受欢迎的语言,那锣鼓喧天、昂首挺胸都是少不了的,没办法,能从全世界这么多编程语言中脱颖而出成为最受欢迎的语言,属实困难。可是有一门语言,它从发布1.0版本开始,连续6年成为了全世界最受欢迎的语言,是的,它就是Rust,这不,2021年又成为最受欢迎的语言了。 @@ -21,7 +19,7 @@ Rust 最早是 Mozilla 雇员 Graydon Hoare 的一个个人项目,从 2009 年 其中第一点是尤为重要的,只有一套成体系的学习教程,才能让用户快速上手并且喜欢上Rust语言,一旦粉丝效应形成,那么Rust在国内的影响力就会在大家的自发宣传下迅速提升。 -#### 国外 +#### 部分主要使用者 - AWS从2017年开始就用Rust实现了它们的无服务器计算平台: AWS Lambda 和 AWS Fargate, 并且用Rust重写了Bottlerocket OS和AWS Nitro系统,这两个是弹性计算云(EC2)的重要服务 - Cloudflare也是Rust的重度用户,DNS、无服务计算、网络包监控等灯 @@ -31,16 +29,68 @@ Rust 最早是 Mozilla 雇员 Graydon Hoare 的一个个人项目,从 2009 年 - Microsoft使用Rust为Azure平台实现了一些组件,其中包括IoT服务的安全守护服务 - githu和npmjs.com,使用Rust提供了高达每天13亿次的npm包下载数量 - Rust目前已经成为全世界区块链平台的首选开发语言 +- Tidb,国内最有名的开源分布式数据库 +- 国内高频交易服务 -类似的还有很多,总之Rust在国外的形式还是非常喜人的,生态发展也异常迅速,颇有燎原之火之势。 - -#### 国内 +类似的还有很多,总之Rust的发展态势非常喜人,生态发展也异常迅速,颇有燎原之火之势。 #### Github -Github上目前的优秀Rust项目还是很多的,具体的可以在这里查看: https://github.com/topics/rust?l=rust,里面的项目是按照star数降序排列。 -## 适用人群 +Github上的Rust项目可以在这里查看: https://github.com/topics/rust?l=rust,里面的项目是按照star数降序排列。 + +## 三、适用人群 + +Rust 因多种原因适用于很多开发者。让我们讨论几个最重要的群体。 + +### 开发者团队 + +由于Rust语言拥有异常强大的编译器和语言特性,因此Rust的代码天然就会比其它语言有更少的Bug,同时Rust拥有非常完善的工具链、最好的包管理工具,这些叠加在一起,决定了Rust非常适合大型开发者团队的协作开发。 + +也许Rust在开发速度上不是最快的,但是从开发 + 维护的角度来看,这个成本绝对是各个语言中最小的之一,当然如果你的公司就追求做出来能用就行,那Rust确实不太适合。 + +### 学生 + +Rust的语言特点决定了它天然就跟底层系统很亲和,通过Rust你能学到操作系统、网络等计算机原理,现在不少名校都引入了Rust作为计算机系统课程学习的重要组成部分,例如MIT对Rust的使用就非常广泛。 + +同时Rust具有一个友善、活跃的社区,社区中的人非常热衷于为大家解答问题,因此也很适合学生学习一门新的恶语言。 + +### 公司 + +数以百计的公司,无论规模大小,都在生产中使用Rust来完成各种任务。这些任务包括命令行工具、web 服务、DevOps 工具、嵌入式设备、音视频分析与转码、加密货币(cryptocurrencies)、生物信息学(bioinformatics)、搜索引擎、物联网(internet of things, IOT)程序、机器学习、云计算等,甚至还包括 Firefox 浏览器的大部分内容。 + +### 开源开发者 + +Rust连续6年成为全世界最受欢迎的语言,这个就是来自于开源社区的厚爱,在github上,Rust目前各种类型的开源项目都非常火,同时有很多领域还等着大家去填补空白,这些都意味着在开源世界扬名立万的机会。 + +为一门成熟的语言锦上添花,远不如为一门新语言雪中送炭,你能获得比在其他语言更多的star和名气。 + + +### 重视速度和稳定性的开发者 + +速度分为两种:运行速度和开发速度。 + +开发速度方面,Rust拥有和C、C++几乎相当的性能,甚至由于Rust的各种零开销抽象以及安全的编程方式,你能轻松写出和那些优化过后的C++代码一样甚至更高的性能: [ripgrep](https://github.com/BurntSushi/ripgrep)就是很典型的例子。 + +同时,在你熟悉Rust后,由于强大的编译器、标准库文档、语言高级特性等,Rust能让你拥有不属于其它静态语言的开发速度,同时大幅减少后期维护成本。 + + +最后,Rust语言不仅仅适用于这些人群,这些列出来的只是从Rust中最受益的人群。总的来说Rust的目标是消除数十年来程序员不得不做的权衡:安全 **与** 生产力,速度 **与** 工程性。 + +请跟随本书的脚步去尝试下Rust,看看这个选择是否适合你。 + +## 四、Rust语言版本更新 + +与其它语言相比,Rust的更新迭代较为频繁(得益于精心设计过的发布流程以及Rust语言开发者团队管理): +- 每6周发布一个迭代版本 +- 2-3年发布一个新的大版本:Rust 2018 edition,Rust 2021 edtion + +好处在于,可以满足不同的用户群体的需求: +- 对于活跃的Rust用户,他们总是能很快获取到新的语言内容,毕竟,尝鲜是技术爱好者的共同特点:) +- 对于一般的用户,edition的发布会告诉这些用户:Rust语言相比上次大版本发布,有了重大的改进,值得一看 +- 对于Rust语言开发者,可以让他们的工作成果更快的被世人所知,不必锦衣夜行 + +具体参见[附录-Rust版本发布](appendix/rust-version.md)。 -## Rust语言版本更新 \ No newline at end of file +好了,相信大家听了这么多Rust的优点,已经迫不及待想要开始学习旅程,OK,let's go. \ No newline at end of file