统一将 literal 翻译成 字面量

This commit is contained in:
Aaran Xu 2022-01-27 01:33:28 +08:00
parent 811ba4a6e1
commit e993d6e0c6
12 changed files with 41 additions and 41 deletions

View File

@ -19,7 +19,7 @@
- `else` - 作为 `if``if let` 控制流结构的 fallback
- `enum` - 定义一个枚举
- `extern` - 链接一个外部 **crate** 、函数或变量
- `false` - 布尔字面 `false`
- `false` - 布尔字面 `false`
- `fn` - 定义一个函数或 **函数指针类型** (*function pointer type*)
- `for` - 遍历一个迭代器或实现一个 trait 或者指定一个更高级的生命周期
- `if` - 基于条件表达式的结果分支
@ -40,7 +40,7 @@
- `struct` - 定义一个结构体
- `super` - 表示当前模块的父模块
- `trait` - 定义一个 trait
- `true` - 布尔字面 `true`
- `true` - 布尔字面 `true`
- `type` - 定义一个类型别名或关联类型
- `unsafe` - 表示不安全的代码、函数、trait 或实现
- `use` - 引入外部空间的符号

View File

@ -77,14 +77,14 @@
| `'ident` | 命名生命周期或循环标签 |
| `...u8`, `...i32`, `...f64`, `...usize`, 等 | 指定类型的数值常量 |
| `"..."` | 字符串常量 |
| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | 原始字符串字面, 未处理的转义字符 |
| `b"..."` | 字节字符串字面; 构造一个 `[u8]` 类型而非字符串 |
| `br"..."`, `br#"..."#`, `br##"..."##`, 等 | 原始字节字符串字面值,原始和字节字符串字面值的结合 |
| `'...'` | 字符字面 |
| `b'...'` | ASCII 码字节字面 |
| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | 原始字符串字面, 未处理的转义字符 |
| `b"..."` | 字节字符串字面; 构造一个 `[u8]` 类型而非字符串 |
| `br"..."`, `br#"..."#`, `br##"..."##`, 等 | 原始字节字符串字面量,原始和字节字符串字面量的结合 |
| `'...'` | 字符字面 |
| `b'...'` | ASCII 码字节字面 |
| <code>&vert;...&vert; expr</code> | 闭包 |
| `!` | 离散函数的总是为空的类型 |
| `_` | “忽略” 模式绑定;也用于增强整型字面的可读性 |
| `_` | “忽略” 模式绑定;也用于增强整型字面的可读性 |
表 B-3 展示了出现在从模块结构到项的路径上下文中的符号
@ -162,7 +162,7 @@
| 符号 | 解释 |
|--------|-------------|
| `()` | 空元组(亦称单元),即是字面也是类型 |
| `()` | 空元组(亦称单元),即是字面也是类型 |
| `(expr)` | 括号表达式 |
| `(expr,)` | 单一元素元组表达式 |
| `(type,)` | 单一元素元组类型 |
@ -179,7 +179,7 @@
| 符号 | 解释 |
|---------|-------------|
| `{...}` | 块表达式 |
| `Type {...}` | `struct` 字面 |
| `Type {...}` | `struct` 字面 |
表 B-10 展示了使用方括号的上下文。

View File

@ -44,7 +44,7 @@ Rust 的核心功能(之一)是 **所有权***ownership*)。虽然该
let s = "hello";
```
变量 `s` 绑定到了一个字符串字面,这个字符串值是硬编码进程序代码中的。这个变量从声明的点开始直到当前 **作用域** 结束时都是有效的。示例 4-1 的注释标明了变量 `s` 在何处是有效的。
变量 `s` 绑定到了一个字符串字面,这个字符串值是硬编码进程序代码中的。这个变量从声明的点开始直到当前 **作用域** 结束时都是有效的。示例 4-1 的注释标明了变量 `s` 在何处是有效的。
```rust
{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}}
@ -65,7 +65,7 @@ let s = "hello";
这里使用 `String` 作为例子,并专注于 `String` 与所有权相关的部分。这些方面也同样适用于标准库提供的或你自己创建的其他复杂数据类型。在[第 8 章][ch8]<!-- ignore -->会更深入地讲解 `String`
我们已经见过字符串字面值,即被硬编码进程序里的字符串值。字符串字面值是很方便的不过它们并不适合使用文本的每一种场景。原因之一就是它们是不可变的。另一个原因是并非所有字符串的值都能在编写代码时就知道例如要是想获取用户输入并存储该怎么办呢为此Rust 有第二个字符串类型,`String`。这个类型管理被分配到堆上的数据,所以能够存储在编译时未知大小的文本。可以使用 `from` 函数基于字符串字面来创建 `String`,如下:
我们已经见过字符串字面量,即被硬编码进程序里的字符串值。字符串字面量是很方便的不过它们并不适合使用文本的每一种场景。原因之一就是它们是不可变的。另一个原因是并非所有字符串的值都能在编写代码时就知道例如要是想获取用户输入并存储该怎么办呢为此Rust 有第二个字符串类型,`String`。这个类型管理被分配到堆上的数据,所以能够存储在编译时未知大小的文本。可以使用 `from` 函数基于字符串字面来创建 `String`,如下:
```rust
let s = String::from("hello");
@ -79,11 +79,11 @@ let s = String::from("hello");
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs:here}}
```
那么这里有什么区别呢?为什么 `String` 可变而字面却不行呢?区别在于两个类型对内存的处理上。
那么这里有什么区别呢?为什么 `String` 可变而字面却不行呢?区别在于两个类型对内存的处理上。
### 内存与分配
就字符串字面来说,我们在编译时就知道其内容,所以文本被直接硬编码进最终的可执行文件中。这使得字符串字面值快速且高效。不过这些特性都只得益于字符串字面值的不可变性。不幸的是,我们不能为了每一个在编译时大小未知的文本而将一块内存放入二进制文件中,并且它的大小还可能随着程序运行而改变。
就字符串字面来说,我们在编译时就知道其内容,所以文本被直接硬编码进最终的可执行文件中。这使得字符串字面量快速且高效。不过这些特性都只得益于字符串字面量的不可变性。不幸的是,我们不能为了每一个在编译时大小未知的文本而将一块内存放入二进制文件中,并且它的大小还可能随着程序运行而改变。
对于 `String` 类型,为了支持一个可变,可增长的文本片段,需要在堆上分配一块在编译时未知大小的内存来存放内容。这意味着:
@ -94,7 +94,7 @@ let s = String::from("hello");
然而,第二部分实现起来就各有区别了。在有 **垃圾回收***garbage collector**GC*)的语言中, GC 记录并清除不再使用的内存,而我们并不需要关心它。没有 GC 的话,识别出不再使用的内存并调用代码显式释放就是我们的责任了,跟请求内存的时候一样。从历史的角度上说正确处理内存回收曾经是一个困难的编程问题。如果忘记回收了会浪费内存。如果过早回收了,将会出现无效变量。如果重复回收,这也是个 bug。我们需要精确的为一个 `allocate` 配对一个 `free`
Rust 采取了一个不同的策略:内存在拥有它的变量离开作用域后就被自动释放。下面是示例 4-1 中作用域例子的一个使用 `String` 而不是字符串字面的版本:
Rust 采取了一个不同的策略:内存在拥有它的变量离开作用域后就被自动释放。下面是示例 4-1 中作用域例子的一个使用 `String` 而不是字符串字面的版本:
```rust
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs:here}}

View File

@ -36,7 +36,7 @@ fn first_word(s: &String) -> ?
因为 `enumerate` 方法返回一个元组,我们可以使用模式来解构,我们将在[第 6 章][ch6]<!-- ignore -->中进一步讨论有关模式的问题。所以在 `for` 循环中,我们指定了一个模式,其中元组中的 `i` 是索引而元组中的 `&item` 是单个字节。因为我们从 `.iter().enumerate()` 中获取了集合元素的引用,所以模式中使用了 `&`
`for` 循环中,我们通过字节的字面语法来寻找代表空格的字节。如果找到了一个空格,返回它的位置。否则,使用 `s.len()` 返回字符串的长度:
`for` 循环中,我们通过字节的字面语法来寻找代表空格的字节。如果找到了一个空格,返回它的位置。否则,使用 `s.len()` 返回字符串的长度:
```rust,ignore
{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:inside_for}}
@ -149,19 +149,19 @@ fn second_word(s: &String) -> &str {
回忆一下借用规则,当拥有某值的不可变引用时,就不能再获取一个可变引用。因为 `clear` 需要清空 `String`,它尝试获取一个可变引用。在调用 `clear` 之后的 `println!` 使用了 `word` 中的引用所以这个不可变的引用在此时必须仍然有效。Rust 不允许 `clear` 中的可变引用和 `word` 中的不可变引用同时存在因此编译失败。Rust 不仅使得我们的 API 简单易用,也在编译时就消除了一整类的错误!
#### 字符串字面就是 slice
#### 字符串字面就是 slice
还记得我们讲到过字符串字面被储存在二进制文件中吗?现在知道 slice 了,我们就可以正确地理解字符串字面了:
还记得我们讲到过字符串字面被储存在二进制文件中吗?现在知道 slice 了,我们就可以正确地理解字符串字面了:
```rust
let s = "Hello, world!";
```
这里 `s` 的类型是 `&str`:它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面是不可变的;`&str` 是一个不可变引用。
这里 `s` 的类型是 `&str`:它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面是不可变的;`&str` 是一个不可变引用。
#### 字符串 slice 作为参数
在知道了能够获取字面`String` 的 slice 后,我们对 `first_word` 做了改进,这是它的签名:
在知道了能够获取字面`String` 的 slice 后,我们对 `first_word` 做了改进,这是它的签名:
```rust,ignore
fn first_word(s: &String) -> &str {

View File

@ -1,6 +1,6 @@
## `match` 控制流运算符
Rust 有一个叫做 `match` 的极为强大的控制流运算符,它允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面、变量、通配符和许多其他内容构成;第 18 章会涉及到所有不同种类的模式以及它们的作用。`match` 的力量来源于模式的表现力以及编译器检查,它确保了所有可能的情况都得到处理。
Rust 有一个叫做 `match` 的极为强大的控制流运算符,它允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面、变量、通配符和许多其他内容构成;第 18 章会涉及到所有不同种类的模式以及它们的作用。`match` 的力量来源于模式的表现力以及编译器检查,它确保了所有可能的情况都得到处理。
可以把 `match` 表达式想象成某种硬币分类器:硬币滑入有着不同大小孔洞的轨道,每一个硬币都会掉入符合它大小的孔洞。同样地,值也会通过 `match` 的每一个模式,并且在遇到第一个 “符合” 的模式时,值会进入相关联的代码块并在执行中被使用。

View File

@ -4,7 +4,7 @@
路径有两种形式:
* **绝对路径***absolute path*)从 crate 根部开始,以 crate 名或者字面 `crate` 开头。
* **绝对路径***absolute path*)从 crate 根部开始,以 crate 名或者字面 `crate` 开头。
* **相对路径***relative path*)从当前模块开始,以 `self`、`super` 或当前模块的标识符开头。
绝对路径和相对路径都后跟一个或多个由双冒号(`::`)分割的标识符。

View File

@ -6,7 +6,7 @@
### 什么是字符串?
在开始深入这些方面之前,我们需要讨论一下术语 **字符串** 的具体意义。Rust 的核心语言中只有一种字符串类型:`str`,字符串 slice它通常以被借用的形式出现`&str`。第 4 章讲到了 **字符串 slice**:它们是一些储存在别处的 UTF-8 编码字符串数据的引用。比如字符串字面被储存在程序的二进制输出中,字符串 slice 也是如此。
在开始深入这些方面之前,我们需要讨论一下术语 **字符串** 的具体意义。Rust 的核心语言中只有一种字符串类型:`str`,字符串 slice它通常以被借用的形式出现`&str`。第 4 章讲到了 **字符串 slice**:它们是一些储存在别处的 UTF-8 编码字符串数据的引用。比如字符串字面被储存在程序的二进制输出中,字符串 slice 也是如此。
称作 `String` 的类型是由标准库提供的而没有写进核心语言部分它是可增长的、可变的、有所有权的、UTF-8 编码的字符串类型。当 Rustacean 们谈到 Rust 的 “字符串”时,它们通常指的是 `String` 和字符串 slice `&str` 类型,而不仅仅是其中之一。虽然本部分内容大多是关于 `String` ,不过这两个类型在 Rust 标准库中都被广泛使用,`String` 和字符串 slice 都是 UTF-8 编码。
@ -22,28 +22,28 @@ let mut s = String::new();
<span class="caption">示例 8-11新建一个空的 `String`</span>
这新建了一个叫做 `s` 的空的字符串,接着我们可以向其中装载数据。通常字符串会有初始数据,因为我们希望一开始就有这个字符串。为此,可以使用 `to_string` 方法,它能用于任何实现了 `Display` trait 的类型,字符串字面也实现了它。示例 8-12 展示了两个例子。
这新建了一个叫做 `s` 的空的字符串,接着我们可以向其中装载数据。通常字符串会有初始数据,因为我们希望一开始就有这个字符串。为此,可以使用 `to_string` 方法,它能用于任何实现了 `Display` trait 的类型,字符串字面也实现了它。示例 8-12 展示了两个例子。
```rust
let data = "initial contents";
let s = data.to_string();
// 该方法也可直接用于字符串字面
// 该方法也可直接用于字符串字面
let s = "initial contents".to_string();
```
<span class="caption">示例 8-12使用 `to_string` 方法从字符串字面创建 `String`</span>
<span class="caption">示例 8-12使用 `to_string` 方法从字符串字面创建 `String`</span>
这些代码会创建包含 `initial contents` 的字符串。
也可以使用 `String::from` 函数来从字符串字面创建 `String`。示例 8-13 中的代码代码等同于使用 `to_string`
也可以使用 `String::from` 函数来从字符串字面创建 `String`。示例 8-13 中的代码代码等同于使用 `to_string`
```rust
let s = String::from("initial contents");
```
<span class="caption">示例 8-13使用 `String::from` 函数从字符串字面创建 `String`</span>
<span class="caption">示例 8-13使用 `String::from` 函数从字符串字面创建 `String`</span>
因为字符串应用广泛,这里有很多不同的用于字符串的通用 API 可供选择。其中一些可能看起来多余,不过都有其用武之地!在这个例子中,`String::from` 和 `to_string` 最终做到了完全相同的事情,所以如何选择,就是风格问题了。

View File

@ -100,7 +100,7 @@ fn main() {
<span class="caption">示例 10-20`main` 函数调用 `longest` 函数来寻找两个字符串 slice 中较长的一个</span>
请注意,这个函数获取作为引用的字符串 slice因为我们不希望 `longest` 函数获取参数的所有权。我们期望该函数接受 `String` 的 slice参数 `string1` 的类型)和字符串字面(包含于参数 `string2`
请注意,这个函数获取作为引用的字符串 slice因为我们不希望 `longest` 函数获取参数的所有权。我们期望该函数接受 `String` 的 slice参数 `string1` 的类型)和字符串字面(包含于参数 `string2`
参考第 4 章中的 [“字符串 slice 作为参数”][string-slices-as-parameters] 部分中更多关于为什么示例 10-20 的参数正符合我们期望的讨论。
@ -447,13 +447,13 @@ impl<'a> ImportantExcerpt<'a> {
### 静态生命周期
这里有一种特殊的生命周期值得讨论:`'static`,其生命周期**能够**存活于整个程序期间。所有的字符串字面都拥有 `'static` 生命周期,我们也可以选择像下面这样标注出来:
这里有一种特殊的生命周期值得讨论:`'static`,其生命周期**能够**存活于整个程序期间。所有的字符串字面都拥有 `'static` 生命周期,我们也可以选择像下面这样标注出来:
```rust
let s: &'static str = "I have a static lifetime.";
```
这个字符串的文本被直接储存在程序的二进制文件中而这个文件总是可用的。因此所有的字符串字面都是 `'static` 的。
这个字符串的文本被直接储存在程序的二进制文件中而这个文件总是可用的。因此所有的字符串字面都是 `'static` 的。
你可能在错误信息的帮助文本中见过使用 `'static` 生命周期的建议,不过将引用指定为 `'static` 之前,思考一下这个引用是否真的在整个程序的生命周期里都有效。你也许要考虑是否希望它存在得这么久,即使这是可能的。大部分情况,代码中的问题是尝试创建一个悬垂引用或者可用的生命周期不匹配,请解决这些问题而不是指定一个 `'static` 的生命周期。

View File

@ -229,7 +229,7 @@ impl Config {
<span class="caption">示例 12-9`Config::new` 中返回 `Result`</span>
现在 `new` 函数返回一个 `Result`,在成功时带有一个 `Config` 实例而在出现错误时带有一个 `&'static str`。回忆一下第 10 章 “静态生命周期” 中讲到 `&'static str` 是字符串字面的类型,也是目前的错误信息。
现在 `new` 函数返回一个 `Result`,在成功时带有一个 `Config` 实例而在出现错误时带有一个 `&'static str`。回忆一下第 10 章 “静态生命周期” 中讲到 `&'static str` 是字符串字面的类型,也是目前的错误信息。
`new` 函数体中有两处修改:当没有足够参数时不再调用 `panic!`,而是返回 `Err` 值。同时我们将 `Config` 返回值包装进 `Ok` 成员中。这些修改使得函数符合其新的类型签名。

View File

@ -2,7 +2,7 @@
模式是 Rust 中特殊的语法,它用来匹配类型中的结构,无论类型是简单还是复杂。结合使用模式和 `match` 表达式以及其他结构可以提供更多对程序控制流的支配权。模式由如下一些内容组合而成:
- 字面
- 字面
- 解构的数组、枚举、结构体或者元组
- 变量
- 通配符

View File

@ -2,9 +2,9 @@
在本书中我们已领略过许多不同类型模式的例子。在本节中,我们收集了模式中所有有效的语法,并讨论了为什么可能要使用每个语法。
### 匹配字面
### 匹配字面
如第 6 章所示,可以直接匹配字面模式。如下代码给出了一些例子:
如第 6 章所示,可以直接匹配字面模式。如下代码给出了一些例子:
```rust
let x = 1;
@ -151,7 +151,7 @@ fn main() {
这段代码创建了变量 `x``y`,与变量 `p` 中的 `x``y` 相匹配。其结果是变量 `x``y` 包含结构体 `p` 中的值。
也可以使用字面作为结构体模式的一部分进行解构,而不是为所有的字段创建变量。这允许我们测试一些字段为特定值的同时创建其他字段的变量。
也可以使用字面作为结构体模式的一部分进行解构,而不是为所有的字段创建变量。这允许我们测试一些字段为特定值的同时创建其他字段的变量。
示例 18-14 展示了一个 `match` 语句将 `Point` 值分成了三种情况:直接位于 `x` 轴上(此时 `y = 0` 为真)、位于 `y` 轴上(`x = 0`)或不在任何轴上的点。
@ -174,11 +174,11 @@ fn main() {
}
```
<span class="caption">示例 18-14: 解构和匹配模式中的字面</span>
<span class="caption">示例 18-14: 解构和匹配模式中的字面</span>
第一个分支通过指定字段 `y` 匹配字面 `0` 来匹配任何位于 `x` 轴上的点。此模式仍然创建了变量 `x` 以便在分支的代码中使用。
第一个分支通过指定字段 `y` 匹配字面 `0` 来匹配任何位于 `x` 轴上的点。此模式仍然创建了变量 `x` 以便在分支的代码中使用。
类似的,第二个分支通过指定字段 `x` 匹配字面 `0` 来匹配任何位于 `y` 轴上的点,并为字段 `y` 创建了变量 `y`。第三个分支没有指定任何字面,所以其会匹配任何其他的 `Point` 并为 `x``y` 两个字段创建变量。
类似的,第二个分支通过指定字段 `x` 匹配字面 `0` 来匹配任何位于 `y` 轴上的点,并为字段 `y` 创建了变量 `y`。第三个分支没有指定任何字面,所以其会匹配任何其他的 `Point` 并为 `x``y` 两个字段创建变量。
在这个例子中,值 `p` 因为其 `x` 包含 0 而匹配第二个分支,因此会打印出 `On the y axis at 7`
@ -227,7 +227,7 @@ fn main() {
这段代码会打印出 `Change the color to red 0, green 160, and blue 255`。尝试改变 `msg` 的值来观察其他分支代码的运行。
对于像 `Message::Quit` 这样没有任何数据的枚举成员,不能进一步解构其值。只能匹配其字面 `Message::Quit`,因此模式中没有任何变量。
对于像 `Message::Quit` 这样没有任何数据的枚举成员,不能进一步解构其值。只能匹配其字面 `Message::Quit`,因此模式中没有任何变量。
对于像 `Message::Move` 这样的类结构体枚举成员,可以采用类似于匹配结构体的模式。在成员名称后,使用大括号并列出字段变量以便将其分解以供此分支的代码使用。这里使用了示例 18-13 所展示的简写。

View File

@ -22,7 +22,7 @@
### 使用 `macro_rules!` 的声明宏用于通用元编程
Rust 最常用的宏形式是 **声明宏***declarative macros*)。它们有时也被称为 “macros by example”、“`macro_rules!` 宏” 或者就是 “macros”。其核心概念是声明宏允许我们编写一些类似 Rust `match` 表达式的代码。正如在第 6 章讨论的那样,`match` 表达式是控制结构,其接收一个表达式,与表达式的结果进行模式匹配,然后根据模式匹配执行相关代码。宏也将一个值和包含相关代码的模式进行比较;此种情况下,该值是传递给宏的 Rust 源代码字面,模式用于和传递给宏的源代码进行比较,同时每个模式的相关代码则用于替换传递给宏的代码。所有这一切都发生于编译时。
Rust 最常用的宏形式是 **声明宏***declarative macros*)。它们有时也被称为 “macros by example”、“`macro_rules!` 宏” 或者就是 “macros”。其核心概念是声明宏允许我们编写一些类似 Rust `match` 表达式的代码。正如在第 6 章讨论的那样,`match` 表达式是控制结构,其接收一个表达式,与表达式的结果进行模式匹配,然后根据模式匹配执行相关代码。宏也将一个值和包含相关代码的模式进行比较;此种情况下,该值是传递给宏的 Rust 源代码字面,模式用于和传递给宏的源代码进行比较,同时每个模式的相关代码则用于替换传递给宏的代码。所有这一切都发生于编译时。
可以使用 `macro_rules!` 来定义宏。让我们通过查看 `vec!` 宏定义来探索如何使用 `macro_rules!` 结构。第 8 章讲述了如何使用 `vec!` 宏来生成一个给定值的 vector。例如下面的宏用三个整数创建一个 vector