diff --git a/src/ch01-02-hello-world.md b/src/ch01-02-hello-world.md index ce56c98..0910ca9 100644 --- a/src/ch01-02-hello-world.md +++ b/src/ch01-02-hello-world.md @@ -14,7 +14,7 @@ Linux 和 Mac: -``` +```text $ mkdir ~/projects $ cd ~/projects $ mkdir hello_world @@ -55,7 +55,7 @@ fn main() { 保存文件,并回到终端窗口。在 Linux 或 OSX 上,输入如下命令: -``` +```text $ rustc main.rs $ ./main Hello, world! @@ -65,7 +65,7 @@ Hello, world! ### 分析 Rust 程序 -现在,让我们回过头来,仔细看看“Hello, world!”程序到底发生了什么。这是拼图的第一片: +现在,让我们回过头来仔细看看 “Hello, world!” 程序到底发生了什么。这是拼图的第一片: ```rust fn main() { @@ -73,37 +73,37 @@ fn main() { } ``` -这几行定义了一个 Rust **函数**。一个叫 `main` 的函数,没有参数也没有返回值。如果有参数的话,它们应该出现在括弧中,`(`和`)`之间。`main` 函数是特殊的:它是每一个可执行的 Rust 程序的入口点。 +这几行定义了一个 Rust **函数**。`main` 函数是特殊的:它是每个可执行的 Rust 程序首先执行的。第一行代码表示 “我声明了一个叫做 `main` 的函数,它没有参数也没有返回值。” 如果有参数的话,他们的名称应该出现在括号中,`(`和`)`之间。 -还须注意函数体被包裹在花括号中,`{`和`}` 之间。所有函数体都要用花括号包裹起来(译者注:有些语言,当函数体只有一行时可以省略花括号,但 Rust 中是不行的)。一般来说,将左花括号与函数声明置于一行,并以空格分隔,是良好的代码风格。 +还须注意函数体被包裹在花括号中,`{`和`}` 之间。Rust 要求所有函数体都要用花括号包裹起来(译者注:有些语言,当函数体只有一行时可以省略花括号,但 Rust 中是不行的)。一般来说,将左花括号与函数声明置于同一行并以空格分隔,是良好的代码风格。 -在 `main()` 函数中: +在 `main()` 函数中: ```rust println!("Hello, world!"); ``` -一行代码完成这个小程序的所有工作:在屏幕上打印文本。这里有很多细节需要注意。首先 Rust 使用 4 个空格的缩进风格,而不是 1 个制表符(tab)。 +这行代码完成这个小程序的所有工作:在屏幕上打印文本。这里有很多细节需要注意。首先 Rust 使用 4 个空格的缩进风格,而不是 1 个制表符(tab)。 -第二个重要的部分是`println!()`。这是 **宏**,Rust 元编程(metaprogramming)的关键所在。而调用一个函数,则要像这样:`println`(没有`!`)。我们将在 21 章 E 小节中更加详细的讨论宏,现在你只需记住,当看到符号 `!` 的时候,调用的是宏而不是普通函数。 +第二个重要的部分是 `println!()`。这给称为 Rust **宏**,Rust 元编程(metaprogramming)的关键所在。如果是调用函数,则应看起来像这样:`println`(没有`!`)。我们将在附录 E 中更加详细的讨论宏,现在你只需记住,当看到符号 `!` 的时候,调用的是宏而不是普通函数。 -接下来,`"Hello, world!"` 是一个 **字符串**。我们把这个字符串作为一个参数传递给`println!`,它负责在屏幕上打印这个字符串。轻松加愉快!(⊙o⊙) +接下来,`"Hello, world!"` 是一个 **字符串**。我们把这个字符串作为一个参数传递给 `println!`,它负责在屏幕上打印这个字符串。轻松加愉快!(⊙o⊙) 该行以分号结尾(`;`)。`;` 代表一个表达式的结束和下一个表达式的开始。大部分 Rust 代码行以 `;` 结尾。 ### 编译和运行是两个步骤 -“编写并运行 Rust 程序”部分,展示了如何创建运行程序。现在我们将拆分并检查每一步操作。 +“编写并运行 Rust 程序” 部分中展示了如何运行新创建的程序。现在我们将拆分并检查每一步操作。 -运行一个 Rust 程序之前,必须先编译它。可以通过 `rustc` 命令来使用 Rust 编译器,并传递源文件的名字给它,如下: +在运行一个 Rust 程序之前必须先进行编译。可以通过 `rustc` 命令来使用 Rust 编译器,并传递源文件的名字给它,如下: -``` +```text $ rustc main.rs ``` -如果你有 C 或 C++ 背景,就会发现这与 `gcc` 和 `clang` 类似。编译成功后,Rust 应该会输出一个二进制可执行文件,在 Linux 或 OSX 上在 shell 中你可以通过`ls`命令看到如下: +如果你有 C 或 C++ 背景,就会发现这与 `gcc` 和 `clang` 类似。编译成功后,Rust 应该会输出一个二进制可执行文件,在 Linux 或 OSX 上在 shell 中可以通过 `ls` 命令看到如下内容: -``` +```text $ ls main main.rs ``` @@ -116,39 +116,39 @@ main.exe main.rs ``` -这表示我们有两个文件:*.rs* 后缀的源文件,和可执行文件(在 Windows下是 *main.exe*,其它平台是 *main*)。然后运行 *main* 或 *main.exe* 文件,像这样: +这表示我们有两个文件:*.rs* 后缀的源文件,和可执行文件(在 Windows下是 *main.exe*,其它平台是 *main*)。余下需要做的就是运行 *main* 或 *main.exe* 文件,如下: -``` +```text $ ./main # or .\main.exe on Windows ``` -如果 *main.rs* 是我们的“Hello, world!”程序,它将会在终端上打印`Hello, world!`。 +如果 *main.rs* 是 “Hello, world!” 程序,它将会在终端上打印 `Hello, world!`。 -来自 Ruby、Python 或 JavaScript 这样的动态类型语言背景的同学,可能不太习惯将编译和执行分为两个步骤。Rust 是一种 **预编译静态类型语言**(*ahead-of-time compiled language*),这意味着编译好程序后,把它给任何人,他们不需要安装 Rust 就可运行。如果你给他们一个 `.rb` , `.py` 或 `.js` 文件,他们需要先分别安装 Ruby,Python,JavaScript 实现(运行时环境,VM),不过你只需要一句命令就可以编译和执行程序。这一切都是语言设计上的权衡取舍。 +来自 Ruby、Python 或 JavaScript 这样的动态类型语言背景的同学,可能不太习惯将编译和执行分为两个单独的步骤。Rust 是一种 **预编译静态类型语言**(*ahead-of-time compiled language*),这意味着你可以编译程序并将其交与他人,他们不需要安装 Rust 即可运行。相反如果你给他们一个 `.rb`、`.py` 或 `.js` 文件,他们需要先分别安装 Ruby,Python,JavaScript 实现(运行时环境,VM),不过你只需要一句命令就可以编译和执行程序。这一切都是语言设计上的权衡取舍。 -使用 `rustc` 编译简单程序是没问题的,不过随着项目的增长,你可能需要控制你项目的方方面面,并且更容易地将代码分享给其它人或项目。所以接下来,我们要介绍一个叫做 Cargo 的工具,它会帮助你编写真实世界中的 Rust 程序。 +使用 `rustc` 编译简单程序是没问题的,不过随着项目的增长,你可能需要控制你项目的方方面面,并且更容易地将代码分享给其它人或项目。接下来,我们要介绍一个叫做 Cargo 的工具,它会帮助你编写真实世界中的 Rust 程序。 ## Hello, Cargo! -Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理他们的 Rust 项目,它使得很多任务变得更轻松。例如,Cargo 负责构建代码、下载依赖库并编译。我们把代码需要的库叫做 **依赖**(*dependencies*)。 +Cargo 是 Rust 的构建系统和包管理工具,同时 Rustacean 们使用 Cargo 来管理他们的 Rust 项目,它使得很多任务变得更轻松。例如,Cargo 负责构建代码、下载依赖库并编译他们。我们把代码需要的库叫做 **依赖**(*dependencies*)。 -最简单的 Rust 程序,比如我们刚刚编写的,并没有任何依赖,所以我们只使用了 Cargo 构建代码的功能。随着更复杂程序的编写,你会想要添加依赖,如果你使用 Cargo 开始的话,这将会变得简单许多。 +最简单的 Rust 程序,比如我们刚刚编写的,并没有任何依赖,所以我们只使用了 Cargo 构建代码的功能。随着编写的程序更加复杂,你会想要添加依赖,如果你使用 Cargo 开始的话,这将会变得简单许多。 -由于绝大部分 Rust 项目使用 Cargo,本书接下来的部分将假设你使用它。如果使用之前介绍的官方安装包的话,它自带 Cargo。如果通过其他方式安装的话,可以在终端输入如下命令,检查是否安装了 Cargo: +由于绝大部分 Rust 项目使用 Cargo,本书接下来的部分将假设你使用它。如果使用之前介绍的官方安装包的话,则自带了 Cargo。如果通过其他方式安装的话,可以在终端输入如下命令检查是否安装了 Cargo: -``` +```text $ cargo --version ``` -如果出现了版本号,一切 OK!如果出现类似“`command not found`”的错误,你应该查看安装文档以确定如何单独安装 Cargo。 +如果出现了版本号,一切 OK!如果出现类似 `command not found` 的错误,你应该查看相应安装文档以确定如何单独安装 Cargo。 ### 使用 Cargo 创建项目 -让我们使用 Cargo 来创建一个新项目,然后看看与上面的`hello_world`项目有什么不同。回到 projects 目录(或者任何你放置代码的目录): +让我们使用 Cargo 来创建一个新项目,然后看看与上面的 `hello_world` 项目有什么不同。回到 projects 目录(或者任何你放置代码的目录): Linux 和 Mac: -``` +```text $ cd ~/projects ``` @@ -158,20 +158,20 @@ Windows: > cd %USERPROFILE%\projects ``` -并在任何操作系统运行: +并在任何操作系统下运行: -``` +```text $ cargo new hello_cargo --bin $ cd hello_cargo ``` -我们向 `cargo new` 传递了 `--bin`,因为我们的目标是生成一个可执行程序,而不是一个库。可执行程序是二进制可执行文件,通常就叫做 **二进制文件**(*binaries*)。项目的名称被定为`hello_cargo`,同时 Cargo 在一个同名目录中创建它的文件,接着我们可以进入查看。 +我们向 `cargo new` 传递了 `--bin`,因为我们的目标是生成一个可执行程序,而不是一个库。可执行程序是二进制可执行文件,通常就叫做 **二进制文件**(*binaries*)。项目的名称被定为 `hello_cargo`,同时 Cargo 在一个同名目录中创建它的文件,接着我们可以进入查看。 -如果列出 *hello_cargo* 目录中的文件,将会看到 Cargo 生成了一个文件和一个目录:一个 *Cargo.toml* 文件和一个 *src* 目录,*main.rs* 文件位于目录中。它也在 *hello_cargo* 目录初始化了一个 git 仓库,以及一个 *.gitignore* 文件;你可以通过`--vcs`参数,切换到其它版本控制系统(VCS),或者不使用 VCS。 +如果列出 *hello_cargo* 目录中的文件,将会看到 Cargo 生成了一个文件和一个目录:一个 *Cargo.toml* 文件和一个 *src* 目录,*main.rs* 文件位于 *src* 目录中。它也在 *hello_cargo* 目录初始化了一个 git 仓库,以及一个 *.gitignore* 文件;你可以通过`--vcs`参数切换到其它版本控制系统(VCS),或者不使用 VCS。 -使用文本编辑器(IDE)打开 *Cargo.toml* 文件。它应该看起来像这样: +使用文本编辑器(工具请随意)打开 *Cargo.toml* 文件。它应该看起来像这样: -Filename: Cargo.toml +文件名: Cargo.toml ```toml [package] @@ -188,11 +188,13 @@ authors = ["Your Name "] 第一行,`[package]`,是一个段落标题,表明下面的语句用来配置一个包。随着我们在这个文件增加更多的信息,还将增加其他段落。 -最后一行,`[dependencies]`,是项目依赖的 *crates*(Rust 代码包)的段落的开始,这样 Cargo 就知道下载和编译它们了。这个项目并不需要任何其他的 crate,不过在下一章猜猜看教程会需要。 +接下来的三行设置了三个 Cargo 所需的配置,他们告诉 Cargo 需要编译这个项目:名称、版本和作者。Cargo 从环境中获取你的名称和 email 信息。如果不正确,请修改并保存此文件。 + +最后一行,`[dependencies]`,是项目依赖的 *crates* 列表(我们这样称呼 Rust 代码包)段落的开始,这样 Cargo 就知道下载和编译它们了。这个项目并不需要任何其他的 crate,不过在下一章猜猜看教程会用得上。 现在看看 *src/main.rs*: -Filename: src/main.rs +文件名: src/main.rs ```rust fn main() { @@ -200,7 +202,7 @@ fn main() { } ``` -Cargo 为你生成了一个“Hello World!”,正如我们之前编写的那个!目前为止,之前项目与 Cargo 生成项目区别有: +Cargo 为你生成了一个 “Hello World!”,正如我们之前编写的那个!目前为止,之前项目与 Cargo 生成项目的区别有: - 代码位于 *src* 目录 - 项目根目录包含一个 *Cargo.toml* 配置文件 @@ -213,14 +215,14 @@ Cargo 期望源文件位于 *src* 目录,将项目根目录留给 README、lic 现在让我们看看通过 Cargo 构建和运行 Hello World 程序有什么不同。为此,输入如下命令: -``` +```text $ cargo build Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) ``` -这应该创建 *target/debug/hello_cargo*(或者在 Windows 上是 *target\debug\hello_cargo.exe*)可执行文件,可以通过这个命令运行: +这应该会创建 *target/debug/hello_cargo*(或者在 Windows 上是 *target\debug\hello_cargo.exe*)可执行文件,可以通过这个命令运行: -``` +```text $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows Hello, world! ``` @@ -229,7 +231,7 @@ Hello, world! 首次运行 `cargo build` 的时候,Cargo 会在项目根目录创建一个新文件,*Cargo.lock*,它看起来像这样: -Filename: Cargo.lock +文件名: Cargo.lock ```toml [root] @@ -237,19 +239,19 @@ name = "hello_cargo" version = "0.1.0" ``` -Cargo 使用 *Cargo.lock* 来记录程序的依赖。这个项目并没有依赖,所以内容比较少。事实上,你自己永远也不需要碰这个文件,让 Cargo 处理它就行了。 +Cargo 使用 *Cargo.lock* 来记录程序的依赖。这个项目并没有依赖,所以其内容比较少。事实上,你自己永远也不需要碰这个文件,让 Cargo 处理它就行了。 -我们刚刚使用 `cargo build` 构建了项目并使用 `./target/debug/hello_cargo` 运行了它,也可以使用 `cargo run` 编译并运行: +我们刚刚使用 `cargo build` 构建了项目并使用 `./target/debug/hello_cargo` 运行了程序,也可以使用 `cargo run` 同时编译并运行: -``` +```text $ cargo run Running `target/debug/hello_cargo` Hello, world! ``` -注意这一次并没有出现“正在编译 `hello_cargo`”的输出。Cargo 发现文件并没有被改变,直接运行了二进制文件。如果修改了源文件的话,将会出现像这样的输出: +注意这一次并没有出现 Cargo 正在编译 `hello_cargo` 的输出。Cargo 发现文件并没有被改变,就直接运行了二进制文件。如果修改了源文件的话,Cargo 会在运行之前重新构建项目,并会出现像这样的输出: -``` +```text $ cargo run Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) Running `target/debug/hello_cargo` @@ -259,24 +261,24 @@ Hello, world! 所以现在又出现更多的不同: - 使用 `cargo build` 构建项目(或使用 `cargo run` 一步构建并运行),而不是使用`rustc` -- 有别于将构建结果放在源码目录,Cargo 将它放到 *target/debug* 目录。 +- 有别于将构建结果放在与源码相同的目录,Cargo 会将其放到 *target/debug* 目录。 -Cargo 的另一个优点是,不管你使用什么操作系统,它的命令都是一样的,所以之后我们将不再为 Linux 和 Mac 以及 Windows 提供相应的命令。 +Cargo 的另一个优点是,不管你使用什么操作系统其命令都是一样的,所以本书之后将不再为 Linux 和 Mac 以及 Windows 提供相应的命令。 -### 发布构建 +### 发布(release)构建 -当项目最终准备好发布了,可以使用 `cargo build --release` 来优化编译项目。这会在 *target/release* 下生成可执行文件,而不是 *target/debug*。优化可以让 Rust 代码运行的更快,然而也需要更长的编译时间。因此产生了两种不同的配置:一种为了开发,你需要快速重新构建;另一种构建给用户的最终程序,不会重新构建,并且程序运行得越快越好。如果你在测试代码的运行时间,请确保运行 `cargo build --release` 并使用 *target/release* 下的可执行文件。 +当项目最终准备好发布了,可以使用 `cargo build --release` 来优化编译项目。这会在 *target/release* 而不是 *target/debug* 下生成可执行文件。这些优化可以让 Rust 代码运行的更快,不过打开他们也需要更长的编译时间。这也就是为什么会有两种两种不同的配置:一种为了开发,你需要经常快速重新构建;另一种构建给用户的最终程序,他们不会重新构建,并且希望程序运行得越快越好。如果你在测试代码的运行时间,请确保运行 `cargo build --release` 并使用 *target/release* 下的可执行文件进行测试。 ### 把 Cargo 当作习惯 -对于简单项目, Cargo 并不比 `rustc` 更有价值,不过随着开发的进行终将体现它的价值。对于拥有多个 crate 的复杂项目,让 Cargo 来协调构建将更简单。有了 Cargo,只需运行`cargo build`,然后一切将有序运行。即便这个项目很简单,也它使用了很多你之后的 Rust 生涯将会用得上的实用工具。其实你可以开始任何你想要从事的项目,使用下面的命令: +对于简单项目, Cargo 并不比 `rustc` 提供了更多的优势,不过随着开发的深入终将证明其价值。对于拥有多个 crate 的复杂项目,让 Cargo 来协调构建将更简单。有了 Cargo,只需运行`cargo build`,然后一切将有序运行。即便这个项目很简单,它现在也使用了很多你之后的 Rust 生涯将会用得上的实用工具。其实你可以使用下面的命令开始任何你想要从事的项目: -``` +```text $ git clone someurl.com/someproject $ cd someproject $ cargo build ``` -> 注意:如果想要了解 Cargo 更多的细节,请阅读官方的 [Cargo guide],它覆盖了所有的功能。 +> 注意:如果想要了解 Cargo 更多的细节,请阅读官方的 [Cargo guide],它覆盖了 Cargo 所有的功能。 [Cargo guide]: http://doc.crates.io/guide.html diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index d9ee27c..c324b1b 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -1,27 +1,27 @@ # 猜猜看 -> [ch02-00-guessing-game-tutorial.md](https://github.com/rust-lang/book/blob/master/src/ch02-00-guessing-game-tutorial.md) +> [ch02-00-guessing-game-tutorial.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch02-00-guessing-game-tutorial.md) >
-> commit e6d6caab41471f7115a621029bd428a812c5260e +> commit 2e269ff82193fd65df8a87c06561d74b51ac02f7 -让我们亲自动手,快速熟悉 Rust!本章将介绍 Rust 中常用的一些概念,并通过真实的程序来展示如何运用。你将会学到更多诸如 `let`、`match`、方法、关联函数、外部 crate 等知识!后继章节会深入探索这些概念的细节。在这一章,我们将练习基础。 +让我们一起动手完成一个项目,来快速上手 RUst!本章将介绍 Rust 中常用的一些概念,并通过真实的程序来展示如何运用他们。你将会学到更多诸如 `let`、`match`、方法、关联函数、外部 crate 等很多的知识!后继章节会深入探索这些概念的细节。在这一章,我们将练习基础。 -我们会实现一个经典的新手编程问题:猜猜看游戏。它是这么工作的:程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,然后提示猜测是大了还是小了。如果猜对了,它会在退出前祝贺你。 +我们会实现一个经典的新手编程问题:猜猜看游戏。它是这么工作的:程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,然后提示猜测是大了还是小了。如果猜对了,它会打印祝贺信息并退出。 ## 准备一个新项目 -要创建一个新项目,进入第一章创建的**项目**目录,使用 Cargo 创建它: +要创建一个新项目,进入第一章中创建的 *projects* 目录,使用 Cargo 新建一个项目,如下: -``` +```text $ cargo new guessing_game --bin $ cd guessing_game ``` -第一个命令,`cargo new`,获取项目的名称(`guessing_game`)作为第一个参数。`--bin`参数告诉 Cargo 创建一个二进制项目,与第一章类似。第二个命令进入到新创建的项目目录。 +第一个命令,`cargo new`,它获取项目的名称(`guessing_game`)作为第一个参数。`--bin` 参数告诉 Cargo 创建一个二进制项目,与第一章类似。第二个命令进入到新创建的项目目录。 看看生成的 *Cargo.toml* 文件: -Filename: Cargo.toml +文件名: Cargo.toml ```toml [package] @@ -34,9 +34,9 @@ authors = ["Your Name "] 如果 Cargo 从环境中获取的开发者信息不正确,修改这个文件并再次保存。 -正如第一章那样,`cargo new` 生成了一个“Hello, world!”程序。查看 *src/main.rs* 文件: +正如第一章那样,`cargo new` 生成了一个 “Hello, world!” 程序。查看 *src/main.rs* 文件: -Filename: src/main.rs +文件名: src/main.rs ```rust fn main() { @@ -44,25 +44,24 @@ fn main() { } ``` -现在让我们使用 `cargo run`,编译运行一步到位: - +现在编译 “Hello, world!” 程序,使用 `cargo run` 编译运行一步到位: -```sh +```text $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Running `target/debug/guessing_game` Hello, world! ``` -`run` 命令适合用在需要快速迭代的项目,而这个游戏就是:我们需要在下一步迭代之前快速测试。 +`run` 命令适合用于需要快速迭代的项目,而这个游戏便是这样的项目:我们需要在下一步迭代之前快速测试。 重新打开 *src/main.rs* 文件。我们将会在这个文件中编写全部代码。 ## 处理一次猜测 -程序的第一部分请求和处理用户输入,并检查输入是否符合预期。首先,需要有一个让玩家输入猜测的地方。在 *src/main.rs* 中输入列表 2-1 中的代码。 +程序的第一部分请求和处理用户输入,并检查输入是否符合预期的格式。首先,允许用户输入猜测。在 *src/main.rs* 中输入列表 2-1 中的代码。 -Filename: src/main.rs +文件名: src/main.rs ```rust,ignore use std::io; @@ -81,9 +80,9 @@ fn main() { } ``` -Listing 2-1: Code to get a guess from the user and print it out +列表 2-1:获取用户猜测并打印的代码 -这些代码包含很多信息,我们一点一点地过一遍。为了获取用户输入并打印结果作为输出,我们需要将 `io`(输入/输出)库引入当前作用域。`io`库来自于标准库(也被称为`std`): +这些代码包含很多信息,我们一点一点地过一遍。为了获取用户输入并打印结果作为输出,我们需要将 `io`(输入/输出)库引入当前作用域。`io` 库来自于标准库(也被称为`std`): ```rust,ignore use std::io; @@ -101,7 +100,7 @@ fn main() { `fn` 语法声明了一个新函数,`()` 表明没有参数,`{` 作为函数体的开始。 -第一章也提及,`println!` 是一个在屏幕上打印字符串的宏: +第一章也提及了 `println!` 是一个在屏幕上打印字符串的宏: ```rust,ignore println!("Guess the number!"); @@ -109,49 +108,49 @@ println!("Guess the number!"); println!("Please input your guess."); ``` -这些代码仅仅打印提示,介绍游戏的内容然后请用户输入。 +这些代码仅仅打印提示,介绍游戏的内容然后请求用户输入。 -### 用变量储存值 +### 使用变量储存值 接下来,创建一个地方储存用户输入,像这样: -```rust +```rust,ignore let mut guess = String::new(); ``` -现在程序开始变得有意思了!这一小行代码发生了很多事。注意这是一个 `let` 语句,用来创建**变量**。这里是另外一个例子: +现在程序开始变得有意思了!这一小行代码发生了很多事。注意这是一个 `let` 语句,用来创建 **变量**。这里是另外一个例子: -```rust +```rust,ignore let foo = bar; ``` -这行代码会创建一个叫做 `foo` 的新变量并把它绑定到值 `bar` 上。在 Rust 中,变量默认是不可变的。下面的例子展示了如何在变量名前使用 `mut` 来使一个变量可变: +这行代码新建了一个叫做 `foo` 的变量并把它绑定到值 `bar` 上。在 Rust 中,变量默认是不可变的。下面的例子展示了如何在变量名前使用 `mut` 来使一个变量可变: ```rust let foo = 5; // immutable let mut bar = 5; // mutable ``` -> 注意:`//` 开始一个注释,它持续到本行的结尾。Rust 忽略注释中的所有内容。 +> 注意:`//` 语法开始一个持续到本行的结尾的注释。Rust 忽略注释中的所有内容。 现在我们知道了 `let mut guess` 会引入一个叫做 `guess` 的可变变量。等号(`=`)的右边是 `guess` 所绑定的值,它是 `String::new` 的结果,这个函数会返回一个 `String` 的新实例。[`String`][string] 是一个标准库提供的字符串类型,它是 UTF-8 编码的可增长文本块。 [string]: https://doc.rust-lang.org/std/string/struct.String.html -`::new` 那一行的 `::` 语法表明 `new` 是 `String` 类型的一个 **关联函数**(*associated function*)。关联函数是针对类型实现的,在这个例子中是 `String`,而不是 `String` 的某个特定实例。一些语言中把它称为**静态方法**(*static method*)。 +`::new` 那一行的 `::` 语法表明 `new` 是 `String` 类型的一个 **关联函数**(*associated function*)。关联函数是针对类型实现的,在这个例子中是 `String`,而不是 `String` 的某个特定实例。一些语言中把它称为 **静态方法**(*static method*)。 -`new` 函数创建了一个新的空 `String`,你会在很多类型上发现`new` 函数,这是创建类型实例的惯用函数名。 +`new` 函数创建了一个新的空 `String`,你会在很多类型上发现 `new` 函数,这是创建类型实例的惯用函数名。 -总结一下,`let mut guess = String::new();` 这一行创建了一个可变变量,绑定到一个新的 `String` 空实例上。 +总结一下,`let mut guess = String::new();` 这一行创建了一个可变变量,当前它绑定到一个新的 `String` 空实例上。 -回忆一下,我们在程序的第一行使用 `use std::io;` 从标准库中引入“输入输出”。现在调用 `io` 的关联函数 `stdin`: +回忆一下,我们在程序的第一行使用 `use std::io;` 从标准库中引入了输入/输出功能。现在调用 `io` 的关联函数 `stdin`: ```rust,ignore io::stdin().read_line(&mut guess) .expect("Failed to read line"); ``` -如果程序的开头没有 `use std::io` 这一行,我们可以把函数调用写成 `std::io::stdin`。`stdin` 函数返回一个 [`std::io::Stdin`][iostdin] 的实例,这代表终端标准输入句柄的类型。 +如果程序的开头没有 `use std::io` 这一行,可以把函数调用写成 `std::io::stdin`。`stdin` 函数返回一个 [`std::io::Stdin`][iostdin] 的实例,这代表终端标准输入句柄的类型。 [iostdin]: https://doc.rust-lang.org/std/io/struct.Stdin.html @@ -159,19 +158,19 @@ io::stdin().read_line(&mut guess) [read_line]: https://doc.rust-lang.org/std/io/struct.Stdin.html#method.read_line -`read_line` 的工作是,无论用户在标准输入中键入什么内容,都将其存入一个字符串中,因此它需要字符串作为参数。这个字符串参数应该是可变的,以便 `read_line` 将用户输入附加上去。 +`read_line` 的工作是,无论用户在标准输入中键入什么内容,都将其存入一个字符串中,因此它需要字符串作为参数。这个字符串参数应该是可变的,以便 `read_line` 将用户输入附加上去。 -`&` 表示这个参数是一个**引用**(*reference*),它允许多处代码访问同一处数据,而无需在内存中多次拷贝。引用是一个复杂的特性,Rust 的一个主要优势就是安全而简单的操纵引用。完成当前程序并不需要了解如此多细节:第四章会更全面的解释引用。现在,我们只需知道它像变量一样,默认是不可变的,需要写成 `&mut guess` 而不是 `&guess` 来使其可变。 +`&` 表示这个参数是一个 **引用**(*reference*),它允许多处代码访问同一处数据,而无需在内存中多次拷贝。引用是一个复杂的特性,Rust 的一个主要优势就是安全而简单的操纵引用。完成当前程序并不需要了解如此多细节:第四章会更全面的解释引用。现在,我们只需知道它像变量一样,默认是不可变的,需要写成 `&mut guess` 而不是 `&guess` 来使其可变。 我们还没有分析完这行代码。虽然这是单独一行代码,但它是一个逻辑行(虽然换行了但仍是一个语句)的第一部分。第二部分是这个方法: -```rust +```rust,ignore .expect("Failed to read line"); ``` -当使用 `.expect()` 语法调用方法时,通过‘换行并缩进’来把长行拆开,是明智的。我们完全可以这样写: +当使用 `.foo()` 语法调用方法时,通过换行并缩进来把长行拆开,是明智的。我们完全可以这样写: -```rust +```rust,ignore io::stdin().read_line(&mut guess).expect("Failed to read line"); ``` @@ -184,19 +183,19 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); [ioresult]: https://doc.rust-lang.org/std/io/type.Result.html [result]: https://doc.rust-lang.org/std/result/enum.Result.html -`Result` 类型是 [*枚举*(*enumerations*)][enums],通常也写作 *enums*。枚举类型持有固定集合的值,这些值被称为枚举的**成员**(*variants*)。第六章将介绍枚举的更多细节。 +`Result` 类型是 [*枚举*(*enumerations*)][enums],通常也写作 *enums*。枚举类型持有固定集合的值,这些值被称为枚举的 **成员**(*variants*)。第六章将介绍枚举的更多细节。 [enums]: ch06-00-enums.html -对于 `Result`,它的成员是 `Ok` 或 `Err`,`Ok` 表示操作成功,内部包含产生的值。`Err` 意味着操作失败,包含失败的前因后果。 +对于 `Result`,它的成员是 `Ok` 或 `Err`,`Ok` 表示操作成功,内部包含成功时产生的值。`Err` 意味着操作失败,包含失败的前因后果。 -`Result` 类型的作用是编码错误处理信息。`Result` 类型的值,像其他类型一样,拥有定义于其上的方法。`io::Result` 的实例拥有[`expect`方法][expect],如果实例的值是 `Err`,`expect` 会导致程序崩溃,并显示当做参数传递给 `expect` 的信息;如果实例的值是 `Ok`,`expect` 会获取 `Ok` 中的值并原样返回。在本例中,这个值是用户输入到标准输入中的字节的数量。 +`Result` 类型的作用是编码错误处理信息。`Result` 类型的值,像其他类型一样,拥有定义于其上的方法。`io::Result` 的实例拥有[`expect` 方法][expect],如果实例的值是 `Err`,`expect` 会导致程序崩溃,并显示当做参数传递给 `expect` 的信息。如果 `read_line` 方法返回 `Err`,则可能是来源于底层操作系统错误的结果。如果 `io::Result` 实例的值是 `Ok`,`expect` 会获取 `Ok` 中的值并原样返回。在本例中,这个值是用户输入到标准输入中的字节的数量。 [expect]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect 如果不使用 `expect`,程序也能编译,不过会出现一个警告: -``` +```text $ cargo build Compiling guessing_game v0.1.0 (file:///projects/guessing_game) src/main.rs:10:5: 10:39 warning: unused result which must be used, @@ -205,7 +204,7 @@ src/main.rs:10 io::stdin().read_line(&mut guess); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` -Rust 警告我们没有使用 `read_line` 的返回值 `Result`,说明有一个可能的错误没处理。想消除警告,就老实的写错误处理,不过我们就是希望程序在出现问题时立即崩溃,所以直接使用 `expect`。第九章会学习如何从错误中恢复。 +Rust 警告我们没有使用 `read_line` 的返回值 `Result`,说明有一个可能的错误没有处理。想消除警告,就老实的写错误处理,不过我们就是希望程序在出现问题时立即崩溃,所以直接使用 `expect`。第九章会学习如何从错误中恢复。 ### 使用 `println!` 占位符打印值 diff --git a/theme/index.hbs b/theme/index.hbs index b7a2621..2127fbe 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -10,7 +10,8 @@ - + + @@ -19,6 +20,13 @@ + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} - + + {{/if}} + + + + @@ -95,6 +113,14 @@ document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E")); } + + + + + + {{#each additional_js}} + + {{/each}} @@ -177,8 +203,15 @@ {{{livereload}}} + {{#if playpens_editable}} + + + + + + {{/if}} + - \ No newline at end of file