Skip to content

Commit dafec9f

Browse files
authored
Merge pull request #72 from ChenApr/master
update rust content
2 parents 7bdb6c3 + a175aee commit dafec9f

File tree

10 files changed

+393
-109
lines changed

10 files changed

+393
-109
lines changed

docs/languages/rust/control.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ for i in (1 .. 10) { // (a .. b) 创建了一个数字序列 Range,表示半
4444
sum += i;
4545
}
4646
// 实际上这里的求和可以通过迭代器用更优雅和快速的方法重写,此处仅仅作为演示。
47+
let word: &str = "World";
48+
for letter in word.chars() { // 将 &str 类型转化为迭代器
49+
println!("{}", letter);
50+
}
51+
// 迭代器的简单示例
4752
```
4853

4954
### `while` 循环

docs/languages/rust/function.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Rust 中通过 `fn` 关键字声明函数,在函数名后的括号内声明参
88
fn func_1() {
99
println!("Hello");
1010
} // 无参数,无返回值的函数
11+
// 无返回值的函数,会默认返回 单位元 ()
1112

1213
fn func_with_param(i: u32, j: u32) {
1314
println!("I love you {} times", i + j);
@@ -29,6 +30,14 @@ fn func_with_return_value_mod(i: i32, j: i32) -> i32 {
2930

3031
在 C/C++ 中,函数的声明的类型在前,没有额外关键字。读者可能需要一些时间来适应 Rust 的语法。
3132

33+
!!! caution "函数返回值"
34+
35+
无返回值的函数会默认返回 **单位元** `()`,并非真实语义下的“无返回值”。
36+
37+
Rust 编译器具有严格的类型检查,如果函数指定了返回值类型,但没有给出返回值或 return 语句,编译器将给出 `mismatched types` 报错。
38+
39+
类似的,如果没给定返回值类型,但返回了 **非单位元** 类型的值,编译器也会给出 `mismatched types` 报错。
40+
3241
## 函数调用
3342

3443
Rust 的函数调用语法与 C/C++ 没有太大区别。

docs/languages/rust/generics.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Rust 的泛型
2+
3+
Rust 中的泛型通过如下方式实现:
4+
5+
## 泛型函数
6+
```rust
7+
fn foo<T, U>(x: T, y: U) {
8+
}
9+
```
10+
11+
## 泛型枚举
12+
```rust
13+
enum Result<T, E> {
14+
Ok(T),
15+
Err(E),
16+
}
17+
```
18+
19+
## 泛型结构体
20+
```rust
21+
struct Point<T> {
22+
x: T,
23+
y: T,
24+
}
25+
26+
impl<T> Point<T> // 在 impl 代码段开头声明泛型
27+
where
28+
T: std::ops::Add<Output = T> + std::ops::Mul<Output = T> + Copy,
29+
{
30+
fn distance_from_origin(&self) -> T {
31+
self.x * self.x + self.y * self.y
32+
}
33+
}
34+
```
35+
36+
## Option 和 Result 类型
37+
Rust 提供了两个非常方便的枚举类型:`Option``Result`
38+
```rust
39+
enum Option<T> {
40+
None,
41+
Some(T),
42+
}
43+
44+
enum Result<T,E> {
45+
Ok(T),
46+
Err(E),
47+
}
48+
```
49+
合理地运用这两个枚举类型,可以便捷地传递参数、捕获错误。
50+
51+
```rust
52+
fn eat(food: Option<String>) {
53+
match food {
54+
Some(c) => println!("Nice {}! I'm full.",c),
55+
None => println!("Nothing to eat. I'm hungry!"),
56+
}
57+
}
58+
59+
fn divide(a: i32, b: i32) -> Result<i32, String>{
60+
if b == 0 {
61+
return Err(String::from("Division by zero"));
62+
}
63+
64+
Ok(a / b)
65+
}
66+
```
67+
68+
!!! note "Option 与 Result 的数据获取"
69+
Rust 为 `Option``Result` 类型提供了 `unwrap()``expect()` 等方法进行快速的数据获取,可以绕开冗余的模式匹配。但程序员需要自己确保 `Option` 对应的类型为 `Some(_)``Result``Ok(_)`),否则会导致程序`panic`退出。
70+
71+
```rust
72+
fn main() {
73+
let a:Option<String> = Some("hello".to_string());
74+
let b: Result<_,&str> = Err("world");
75+
let content = a.unwrap() + " " + b.expect("Empty content"); // If a is None or b is Err, this will panic.
76+
// a is None: thread 'main' panicked at ...:
77+
// called `Option::unwrap()` on a `None` value
78+
// b is Err:thread 'main' panicked at ...:
79+
// Empty content: "world"
80+
println!("{}",content);
81+
}
82+
```
83+

docs/languages/rust/index.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,25 @@
1616

1717
不同于 JavaScript 和 Python 等语言,Rust 语言上手相对较为困难。因此,编写本文档的目的更类似于在假定读者拥有一定 C++ 基础的情况下,向读者提供一些学习 Rust 的对照性帮助,而非一个 Rust 入门教程。如果希望获得一份 Rust 入门教程,请参阅下方资源链接中的 The Book。
1818

19-
本文档覆盖了 The Book 的 第3(常见编程概念)、5(结构体)、6(枚举和模式匹配)章的主要内容,介绍了最为基本的语法,且不怎么涉及新概念(如所有权、生命周期
19+
本文档覆盖了 The Book 的 第3(常见编程概念)、5(结构体)、6(枚举和模式匹配)章的主要内容,介绍了最为基本的语法。在文档的开头,将简要介绍 Rust 中的所有权。生命周期、不安全代码、自动测试等高级概念,可以参考下述资源链接自行学习
2020

2121
## 资源链接
2222

23-
- The Rust Programming Language(也被称为 The Book)。Rust 官方网站推荐的 Rust 语言入门书籍 https://doc.rust-lang.org/book/
23+
### 官方参考资料
24+
- The Rust Programming Language(也被称为 The Book):Rust 官方网站推荐的 Rust 语言入门书籍 https://doc.rust-lang.org/book/
2425
- The Book 的中文社区翻译版,更新很及时 https://kaisery.github.io/trpl-zh-cn/
2526

26-
- Rustlings。Rust 官方推荐的另一种入门方式,适合喜欢边学边做的同学 https://github.com/rust-lang/rustlings/
27+
- Rustlings:Rust 官方推荐的另一种入门方式,适合喜欢边学边做的同学 https://github.com/rust-lang/rustlings/
28+
29+
### 入门教程
30+
- Rust 官方文档中文教程。https://rustwiki.org
31+
32+
- RUNOOB.COM 的 Rust 教程:简明的入门教程,可作为第一份学习资料。https://www.runoob.com/rust/rust-tutorial.html
33+
34+
### 阅读材料
35+
- Effective Rust:Rust 进阶教程,比较详细地介绍了 Rust 中类型(Types)、特型(Trait)及 Rust 语言的设计理念和使用方法。 https://www.lurklurk.org/effective-rust/
36+
37+
### 课程材料
38+
- CIS 198: Rust Programming:宾夕法尼亚大学的 Rust 课程。https://cis198-2016s.github.io
39+
40+
- 清华大学程序设计训练(Rust)文档。https://lab.cs.tsinghua.edu.cn/rust/

docs/languages/rust/matching.md

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,24 @@ let coin = Coin {
2222
};
2323
```
2424

25-
Rust 的枚举量中可以保存数据成员,十分强大。
25+
枚举的每种变体 (variant) 可以:
26+
27+
- 没有数据(单位元变体)
28+
- 有命名的数据域(结构体变体)
29+
- 有不命名的有序数据域(元组变体)
2630

2731
```rust
28-
enum Coin {
29-
Dime(u32),
30-
Half(u32),
31-
Yuan(u32)
32-
} // 在一个枚举类型中完成类型和面值的记录
33-
34-
let coin = Coin::Dime(10);
35-
36-
enum AnotherEnum {
37-
TypeA(i32),
38-
TypeB(u32, f64),
39-
TypeC(String),
40-
TypeD
41-
} // 枚举类型的数据成员可以互不相同
32+
enum Resultish {
33+
Ok,
34+
Warning { code: i32, message: String },
35+
Err(String)
36+
}
4237
```
4338

4439
!!! note "与 C++ 的对照"
4540

46-
C/C++ 的枚举类型底层是整数,不能拥有数据成员。这是 Rust 和 C/C++ 的一个很大的区别。枚举类型是 Rust 提供给我们的有力武器。
41+
C/C++ 的枚举类型底层是整数,不能拥有数据成员。这是 Rust 和 C/C++ 的一个很大的区别。
42+
枚举类型是 Rust 提供给我们的有力武器。善用枚举类,可以便捷地传递很多数据。
4743

4844
## 匹配
4945

docs/languages/rust/ownership.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Rust 中的所有权
2+
3+
为了兼顾内存使用的**安全****性能**,Rust 在设计之初就采用了与 C++ 完全不同的内存管理。
4+
5+
Rust 引入了**所有权(ownership)**的概念:
6+
7+
- Rust 中的每个值都有所有者 (owner)。
8+
- 同一时刻每个值只有一个所有者。
9+
- 当所有者失效,值也将被丢弃。
10+
11+
变量通过绑定的方式,获得对数据的所有权。如果一个绑定超出作用域,其绑定的数据将被自动释放
12+
13+
```rust
14+
let a = 1;
15+
```
16+
17+
变量之间的**赋值**行为,将会直接导致绑定关系的变化,这一语义被称为**移动所有权**,亦即**掩盖 (shadowing)**
18+
19+
```rust
20+
let s1 = String::from("hello");
21+
let s2 = s1; // 字符串 "hello" 已经被 s2 绑定,s1 悬置。
22+
23+
println!("{s1}, world!");
24+
// 此时将发生编译错误 error: borrow of moved value: `s1`
25+
```
26+
27+
但并非所有语境下的变量赋值都希望移交所有权,这个时候应该采用 Rust 中的**借用(borrow)**概念。
28+
29+
```rust
30+
let v = vec![1, 2, 3];
31+
let v_ref = &v; // v_ref is a reference to v.
32+
```
33+
34+
!!! note "移动所有权"
35+
- 移动所有权是编译时的语义,不涉及程序运行时的数据移动,数据对应的内存区域并没有改变,只是更改了对应的变量名(类似C++的指针)。
36+
- 移动是默认行为(通过绑定或赋值),不需要像 C++ 那样用 std::move 来显式指定。
37+
- 原来的变量依然拥有对数据的所有权。
38+
39+
40+
当借用发生时,会对原来的变量增加限制:
41+
- 当一个变量有引用存在时,不能移交它所绑定的数据的所有权。
42+
43+
```rust
44+
let v = vec![1, 2, 3];
45+
let v_ref = &v;
46+
let v_new = v;
47+
// Moving ownership to v_new would invalidate v_ref.
48+
// error: cannot move out of `v` because it is borrowed
49+
```
50+
51+
Rust 类型系统中,变量被分为**可变****不可变**。在借用中,同理可分为**可变借用** `&mut`**不可变借用** `&`
52+
```rust
53+
fn main() {
54+
let mut vector: Vec<i32> = vec![];
55+
let vector_ref: &mut Vec<i32> = &mut vector;
56+
push(vector_ref, 4);
57+
}
58+
```
59+
60+
!!! note "借用规则"
61+
- 不能在某个对象不存在后继续保留对它的引用。一个对象可以
62+
- 同时存在**多个不可变**引用(&T)
63+
- 或者**仅有一个可变引用**(&mut T)。
64+
- 以上两者不能同时存在
65+
66+
需要注意的是,**函数****参数传递**时,采用的是与变量赋值和借用相同的语法规则。如果不指定 `&``&mut`,变量会直接发生移动。
67+
```rust
68+
fn hello_move(s: String) {
69+
println!("Message by moving: {}", S);
70+
}
71+
72+
fn hello_borrow(s: &String) {
73+
println!("Message by borrowing: {}", S);
74+
}
75+
76+
fn main() {
77+
let x: String = String::from("hello");
78+
let y: String = String::from("hello");
79+
80+
hello_move(x);
81+
hello_borrow(&y);
82+
83+
println!("x:{}",x); // error[E0382]: borrow of moved value: `x`
84+
println!("y:{}",y); // This runs normally.
85+
}
86+
87+
```
88+
89+
!!! note "变量的拷贝"
90+
如果想要直接获得一份变量的副本,可以使用 Rust 的 Copy 特型。
91+
92+
- 大多数基本类型是 Copy 类型(i32、f64、char、bool 等等)。
93+
- 基本类型发生赋值时,会发生拷贝而非移动。
94+
95+
96+
```rust
97+
let x: i32 = 12;
98+
let y = x; // `i32` is `Copy`, so it's not moved :D
99+
println!("x still works: {}, and so does y: {}", x, y);
100+
```
101+
102+
- 可以通过 `impl Copy for ...` 或 `#[derive(Copy)]` 宏为变量实现 Copy 特型
103+
- 非基本类型在实现了 Copy 特型后,可以通过 `clone()` 等方法进行拷贝。
104+
105+
```rust
106+
let x: String = String::from("hello");
107+
let y = x.clone(); // here copy an 'x' to y
108+
println!("x still works: {}, and so does y: {}", x, y);
109+
```
110+
所有权的思想贯穿了 Rust 编程的全过程,在后续的 **变量****函数****结构体** 等章节中,你还会多次遇到所有权的**转移****借用**问题。

0 commit comments

Comments
 (0)