|
|
|
@ -33,7 +33,7 @@ fn main() {
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
以上代码有以下几点要注意:
|
|
|
|
|
- **`if`语句块是表达式**,这里我们使用`if`表达式的返回值来给`number`进行赋值:`number`的值是`5`。
|
|
|
|
|
- **`if` 语句块是表达式**,这里我们使用 `if` 表达式的返回值来给 `number` 进行赋值:`number` 的值是 `5`
|
|
|
|
|
- 用 `if` 来赋值时,要保证每个分支返回的类型一样(事实上,这种说法不完全准确,见[这里](../appendix/expressions.md#if表达式)),此处返回的 `5` 和 `6` 就是同一个类型,如果返回类型不一致就会报错
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
@ -99,9 +99,9 @@ for 元素 in 集合 {
|
|
|
|
|
// 使用元素干一些你懂我不懂的事情
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
这个语法跟`javascript`还蛮像,应该挺好理解。
|
|
|
|
|
这个语法跟 JavaScript 还蛮像,应该挺好理解。
|
|
|
|
|
|
|
|
|
|
注意,使用`for`时我们往往使用集合的引用形式,除非你不想在后面的代码中继续使用该集合(比如我们这里使用了container的引用)。如果不使用引用的话,所有权会被转移到`for`语句块中,后面就无法再使用这个集合了):
|
|
|
|
|
注意,使用 `for` 时我们往往使用集合的引用形式,除非你不想在后面的代码中继续使用该集合(比如我们这里使用了 `container` 的引用)。如果不使用引用的话,所有权会被转移到 `for` 语句块中,后面就无法再使用这个集合了):
|
|
|
|
|
```rust
|
|
|
|
|
for item in &container {
|
|
|
|
|
// ...
|
|
|
|
@ -160,10 +160,10 @@ for item in collection {
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
第一种方式是循环索引,然后通过索引下标去访问集合,第二种方式是直接循环集合中的元素,优劣如下:
|
|
|
|
|
- **性能**:第一种使用方式中`collection[index]`的索引访问,会因为边界检查(bounds checking)导致运行时的性能损耗 - Rust会检查并确认`index`是否落在集合内,但是第二种直接迭代的方式就不会触发这种检查,因为编译器会在编译时就完成分析并证明这种访问是合法的
|
|
|
|
|
- **性能**:第一种使用方式中 `collection[index]` 的索引访问,会因为边界检查(Bounds Checking)导致运行时的性能损耗 —— Rust会检查并确认 `index` 是否落在集合内,但是第二种直接迭代的方式就不会触发这种检查,因为编译器会在编译时就完成分析并证明这种访问是合法的
|
|
|
|
|
- **安全**:第一种方式里对 `collection` 的索引访问是非连续的,存在一定可能性在两次访问之间,`collection` 发生了变化,导致脏数据产生。而第二种直接迭代的方式是连续访问,因此不存在这种风险(这里是因为所有权吗?是的话可能要强调一下)
|
|
|
|
|
|
|
|
|
|
由于for循环无需任何条件限制,也不需要通过索引来访问,因此是最安全也是最常用的,通过与下面的`while`的对比,我们能看到为什么`for`会更加安全。
|
|
|
|
|
由于 `for` 循环无需任何条件限制,也不需要通过索引来访问,因此是最安全也是最常用的,通过与下面的 `while` 的对比,我们能看到为什么 `for` 会更加安全。
|
|
|
|
|
|
|
|
|
|
#### `continue`
|
|
|
|
|
使用 `continue` 可以跳过当前当次的循环,开始下次的循环:
|
|
|
|
@ -183,7 +183,7 @@ for item in collection {
|
|
|
|
|
|
|
|
|
|
#### while循环
|
|
|
|
|
|
|
|
|
|
如果你需要一个条件来循环,当该条件为`true`时,继续循环,条件为`false`,跳出循环,那么`while`就非常适用:
|
|
|
|
|
如果你需要一个条件来循环,当该条件为 `true` 时,继续循环,条件为 `false`,跳出循环,那么 `while` 就非常适用:
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut n = 0;
|
|
|
|
@ -209,7 +209,7 @@ fn main() {
|
|
|
|
|
我出来了!
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
当然,你也可以用其它方式组合实现,例如`loop`(无条件循环,将在下面介绍) + `if` + `break`:
|
|
|
|
|
当然,你也可以用其它方式组合实现,例如 `loop`(无条件循环,将在下面介绍) + `if` + `break`:
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut n = 0;
|
|
|
|
@ -251,9 +251,9 @@ the value is: 40
|
|
|
|
|
the value is: 50
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
数组中的所有五个元素都如期被打印出来。尽管 index 在某一时刻会到达值 5,不过循环在其尝试从数组获取第六个值(会越界)之前就停止了。
|
|
|
|
|
数组中的所有五个元素都如期被打印出来。尽管 `index` 在某一时刻会到达值 5,不过循环在其尝试从数组获取第六个值(会越界)之前就停止了。
|
|
|
|
|
|
|
|
|
|
但这个过程很容易出错;如果索引长度不正确会导致程序 panic。这也使程序更慢,因为编译器增加了运行时代码来对每次循环的每个元素进行条件检查。
|
|
|
|
|
但这个过程很容易出错;如果索引长度不正确会导致程序 ***panic***。这也使程序更慢,因为编译器增加了运行时代码来对每次循环的每个元素进行条件检查。
|
|
|
|
|
|
|
|
|
|
`for`循环代码如下:
|
|
|
|
|
```rust
|
|
|
|
@ -270,9 +270,9 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### loop循环
|
|
|
|
|
对于循环而言,`loop`循环毋庸置疑,是适用面最高的,它可以适用于所有循环场景(虽然能用,但是在很多场景下,`for`和`while`才是最优选择),因为loop就是一个简单的无限循环,你可以在内部实现逻辑通过`break`关键字来控制循环何时结束。
|
|
|
|
|
对于循环而言,`loop` 循环毋庸置疑,是适用面最高的,它可以适用于所有循环场景(虽然能用,但是在很多场景下, `for` 和 `while` 才是最优选择),因为 `loop` 就是一个简单的无限循环,你可以在内部实现逻辑通过 `break` 关键字来控制循环何时结束。
|
|
|
|
|
|
|
|
|
|
使用`loop`循环一定要打起精神,否则你会写出下面的跑满你一个cpu核心的疯子代码:
|
|
|
|
|
使用 `loop` 循环一定要打起精神,否则你会写出下面的跑满你一个 CPU 核心的疯子代码:
|
|
|
|
|
```rust,ignore
|
|
|
|
|
fn main() {
|
|
|
|
|
loop {
|
|
|
|
|