From 3c8ba8dc5fee57cb68a7b7ab6c8b9984e047928a Mon Sep 17 00:00:00 2001 From: wayslog Date: Thu, 5 May 2016 01:30:24 +0800 Subject: [PATCH 1/2] reformat as double blank in line tail --- README.md | 4 -- .../message-passing.md | 13 ++++-- data-structure/stack.md | 14 +++---- flow/repetition.md | 5 ++- generic/generic.md | 21 +++++----- match/pattern.md | 2 +- ownership-system/ownership.md | 30 ++++++------- quickstart/primitive-type.md | 6 +-- quickstart/rust-travel.md | 42 +++++++++---------- quickstart/trait.md | 2 + rcarc/rcarc.md | 2 - 11 files changed, 72 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 412a1c0..4542582 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ # RustPrimer -[![build status][build-badge]][build-url] - -[build-badge]: https://api.travis-ci.org/rustcc/RustPrimer.svg -[build-url]: https://travis-ci.org/rustcc/RustPrimer The Rust primer for beginners. 给初学者的Rust中文教程。 diff --git a/concurrency-parallel-thread/message-passing.md b/concurrency-parallel-thread/message-passing.md index 316fea6..1770086 100644 --- a/concurrency-parallel-thread/message-passing.md +++ b/concurrency-parallel-thread/message-passing.md @@ -12,7 +12,8 @@ use std::thread; fn main() { // 创建一个通道 - let (tx, rx): (mpsc::Sender, mpsc::Receiver) = mpsc::channel(); + let (tx, rx): (mpsc::Sender, mpsc::Receiver) = + mpsc::channel(); // 创建线程用于发送消息 thread::spawn(move || { @@ -60,7 +61,8 @@ impl fmt::Display for Student { fn main() { // 创建一个通道 - let (tx, rx): (mpsc::Sender>, mpsc::Receiver>) = mpsc::channel(); + let (tx, rx): (mpsc::Sender>, mpsc::Receiver>) = + mpsc::channel(); // 创建线程用于发送消息 thread::spawn(move || { @@ -76,7 +78,8 @@ fn main() { ``` 编译代码,奇迹没有出现,编译时错误,错误提示: ``` -error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc` [E0277] +error: the trait `core::marker::Send` is not +implemented for the type `alloc::rc::Rc` [E0277] note: `alloc::rc::Rc` cannot be sent between threads safely ``` 看来并不是所有类型的消息都可以通过通道发送,消息类型必须实现`marker trait Send`。Rust之所以这样强制要求,主要是为了解决并发安全的问题,再一次强调,**安全**是Rust考虑的重中之重。如果一个类型是`Send`,则表明它可以在线程间安全的转移所有权(`ownership`),当所有权从一个线程转移到另一个线程后,同一时间就只会存在一个线程能访问它,这样就避免了数据竞争,从而做到线程安全。`ownership`的强大又一次显示出来了。通过这种做法,在编译时即可要求所有的代码必须满足这一约定,这种方式方法值得借鉴,`trait`也是非常强大。 @@ -143,7 +146,9 @@ receive 2 在代码中,我们故意让`main`所在的主线程睡眠2秒,从而让发送者所在线程优先执行,通过结果可以发现,发送者发送消息时确实没有阻塞。还记得在前面提到过很多关于通道的问题吗?从这个例子里面还发现什么没?除了不阻塞之外,我们还能发现另外的三个特征: 1. 通道是可以同时支持多个发送者的,通过`clone`的方式来实现。 - 这类似于`Rc`的共享机制,其实从`Channel`所在的库名`std::sync::mpsc`也可以知道这点,因为`mpsc`就是多生产者单消费者(Multiple Producers Single Consumer)的简写。 + 这类似于`Rc`的共享机制。 + 其实从`Channel`所在的库名`std::sync::mpsc`也可以知道这点。 + 因为`mpsc`就是多生产者单消费者(Multiple Producers Single Consumer)的简写。 可以有多个发送者,但只能有一个接收者,即支持的N:1模式。 2. 异步通道具备消息缓存的功能,因为1和2是在没有接收之前就发了的,在此之后还能接收到这两个消息。 diff --git a/data-structure/stack.md b/data-structure/stack.md index 3040849..3e42c0d 100644 --- a/data-structure/stack.md +++ b/data-structure/stack.md @@ -43,18 +43,18 @@ struct StackNode { >现在我们重点来看看第四行: 我们**从里到外**拆分来看看,首先是`Box`,这里的`Box`是 Rust 用来显式分配堆内存的类型: -> `pub struct Box where T: ?Sized(_);` +> `pub struct Box where T: ?Sized(_);` [详细文档请参考Rust的标准库](http://doc.rust-lang.org/nightly/std/boxed/struct.Box.html) -> 在 Rust 里面用强大的类型系统做了统一的抽象。在这里相当于在堆空间里申请了一块内存保存`StackNode`。 +> 在 Rust 里面用强大的类型系统做了统一的抽象。在这里相当于在堆空间里申请了一块内存保存`StackNode`。 -> **为什么要这么做了?如果不用Box封装会怎么样呢?** +> **为什么要这么做了?如果不用Box封装会怎么样呢?** -> 如果不用 Box 封装,rustc 编译器会报错,在 Rust 里面,rustc 默认使用栈空间,但是这里的`StackNode`定义的时候使用了递归的数据结构,next 属性的类型是 `StackNode`,而这个类型是无法确定大小的,所有这种无法确定大小的类型,都不能保存在栈空间。所以需要使用`Box`来封装。这样的话`next`的类型就是一个指向某一块堆空间的指针,而指针是可以确定大小的,因此能够保存在栈空间。 +> 如果不用 Box 封装,rustc 编译器会报错,在 Rust 里面,rustc 默认使用栈空间,但是这里的`StackNode`定义的时候使用了递归的数据结构,next 属性的类型是 `StackNode`,而这个类型是无法确定大小的,所有这种无法确定大小的类型,都不能保存在栈空间。所以需要使用`Box`来封装。这样的话`next`的类型就是一个指向某一块堆空间的指针,而指针是可以确定大小的,因此能够保存在栈空间。 -> **那么为什么还需要使用`Option`来封装呢?** +> **那么为什么还需要使用`Option`来封装呢?** -> `Option`是 Rust 里面的一个抽象类型,定义如下: +> `Option`是 Rust 里面的一个抽象类型,定义如下: > ```rust pub enum Option { @@ -103,7 +103,7 @@ impl Stack { - `new( )`比较简单,Stack 初始化的时候为空,栈顶元素 `top` 就没有任何值,所以 `top` 为 `None`。 - `push( )`的主要功能是往栈里面推入元素,把新的 StackNode 指向 Stack 里面旧的值,同时更新 Stack 栈顶指向新进来的值。 -> 这里有个需要注意的地方是第8行代码里面,`let next = self.top.take();`,使用了 Option 类型的 take 方法: +> 这里有个需要注意的地方是第8行代码里面,`let next = self.top.take();`,使用了 Option 类型的 take 方法: `fn take(&mut self) -> Option` 它会把 Option 类型的值取走,并把它的元素改为 None diff --git a/flow/repetition.md b/flow/repetition.md index 3273bc5..3789beb 100644 --- a/flow/repetition.md +++ b/flow/repetition.md @@ -74,7 +74,10 @@ i = 4 and j = 9 再比如: ```rust -let lines = "Content of line one\nContent of line two\nContent of line three\nContent of line four".lines(); +let lines = "Content of line one +Content of line two +Content of line three +Content of line four".lines(); for (linenumber, line) in lines.enumerate() { println!("{}: {}", linenumber, line); } diff --git a/generic/generic.md b/generic/generic.md index 5a0a8f1..bdcf9ca 100644 --- a/generic/generic.md +++ b/generic/generic.md @@ -1,7 +1,6 @@ 泛型 =================== ----------- 我们在编程中,通常有这样的需求,为多种类型的数据编写一个功能相同的函数,如两个数的加法,希望这个函数既支持i8、i16、 i32 ....float64等等,甚至自定义类型,在不支持泛型的编程语言中,我们通常要为每一种类型都编写一个函数,而且通常情况下函数名还必须不同,例如: ```rust fn add_i8(a:i8, b:i8) -> i8 { @@ -79,9 +78,9 @@ fn main() { } ``` ->**输出:** ->101 ->200.33 +>**输出:** +>101 +>200.33 ```add>(a:T, b:T) -> T```就是我们泛型函数,返回值也是泛型T,Add<>中的含义可以暂时忽略,大体意思就是只要参数类型实现了Add trait,就可以被传入到我们的add函数,因为我们的add函数中有相加+操作,所以要求传进来的参数类型必须是可相加的,也就是必须实现了Add trait(具体参考std::ops::Add)。 @@ -120,10 +119,10 @@ fn main() { println!("{:?}", add(p1, p2)); } ``` ->**输出:** ->101 -200.33 -Point { x: 3, y: 3 } +>**输出:** +>101 +200.33 +Point { x: 3, y: 3 } 上面的例子稍微更复杂些了,只是我们增加了自定义的类型,然后让add函数依然可以在上面工作。如果对trait不熟悉,请查阅trait相关章节。 @@ -163,9 +162,9 @@ fn main() { } ``` ->**输出:** ->Point { x: 3.2, y: 3.2 } -Point { x: 3, y: 3 } +>**输出:** +>Point { x: 3.2, y: 3.2 } +Point { x: 3, y: 3 } 上面的列子更复杂了些,我们不仅让自定义的Point类型支持了add操作,同时我们也为Point做了泛型化。 diff --git a/match/pattern.md b/match/pattern.md index 73ea18f..2465a81 100644 --- a/match/pattern.md +++ b/match/pattern.md @@ -26,7 +26,7 @@ x: 1 在以上代码中,match作用域里的`x`这个变量被覆盖成了`'c'`,而出了这个作用域之后,变量又恢复成了原来的值。这和变量绑定的行为是一致的。 -## 更强大的结构 +## 更强大的解构 在上一节里,我们初步了解了模式匹配在解构`enum`时候的便利性,事实上,在Rust中模式可以被用来对任何复合类型进行解构——struct/tuple/enum。现在我们要进行一个复杂点的例子,对`struct`进行解构。 diff --git a/ownership-system/ownership.md b/ownership-system/ownership.md index 0d61d63..720c360 100644 --- a/ownership-system/ownership.md +++ b/ownership-system/ownership.md @@ -85,11 +85,11 @@ c.rs:4 println!("{}", a); let 标识符A = 标识符B; // 把“A”绑定资源的所有权转移给“B” ``` Move前后的内存示意如下: -> **Before move:** -a <=> 内存(地址:**A**,内容:"xyz") -**After move:** -a -b <=> 内存(地址:**A**,内容:"xyz") +> **Before move:** +a <=> 内存(地址:**A**,内容:"xyz") +**After move:** +a +b <=> 内存(地址:**A**,内容:"xyz") 被move的变量不可以继续被使用。否则提示错误`error: use of moved value`。 @@ -106,11 +106,11 @@ b <=> 内存(地址:**A**,内容:"xyz") ``` 编译确实可以通过,输出为`100`。这是为什么呢,是不是跟move小节里的结论相悖了? 其实不然,这其实是根据变量类型是否实现`Copy`特性决定的。对于实现`Copy`特性的变量,在move时会拷贝资源到新内存区域,并把新内存区域的资源`binding`为`b`。 -> **Before move:** -a <=> 内存(地址:**A**,内容:100) -**After move:** -a <=> 内存(地址:**A**,内容:100) -b <=> 内存(地址:**B**,内容:100) +> **Before move:** +a <=> 内存(地址:**A**,内容:100) +**After move:** +a <=> 内存(地址:**A**,内容:100) +b <=> 内存(地址:**B**,内容:100) move前后的`a`和`b`对应资源内存的地址不同。 @@ -129,11 +129,11 @@ move前后的`a`和`b`对应资源内存的地址不同。 这个时候可以编译通过,并且成功打印"xyz"。 clone后的效果等同如下: -> **Before move:** -a <=> 内存(地址:**A**,内容:"xyz") -**After move:** -a <=> 内存(地址:**A**,内容:"xyz") -b <=> 内存(地址:**B**,内容:"xyz") +> **Before move:** +a <=> 内存(地址:**A**,内容:"xyz") +**After move:** +a <=> 内存(地址:**A**,内容:"xyz") +b <=> 内存(地址:**B**,内容:"xyz") 注意,然后a和b对应的资源值相同,但是内存地址并不一样。 diff --git a/quickstart/primitive-type.md b/quickstart/primitive-type.md index 3f435c1..37c8a70 100644 --- a/quickstart/primitive-type.md +++ b/quickstart/primitive-type.md @@ -42,9 +42,9 @@ fn main() { **例如:** 固定大小类型: -> 1u8 1i8 -> 1u16 1i16 -> 1u32 1i32 +> 1u8 1i8 +> 1u16 1i16 +> 1u32 1i32 > 1u64 1i64 可变大小类型: diff --git a/quickstart/rust-travel.md b/quickstart/rust-travel.md index ee0def5..897821a 100644 --- a/quickstart/rust-travel.md +++ b/quickstart/rust-travel.md @@ -8,10 +8,10 @@ - 创建一个 Doing 目录和 helloworld.rs 文件 -> ps: mkdir ~/Doing -> ps: cd ~/Doing -> ps: notepad helloworld.rs # 作者偏向于使用 sublime 作为编辑器 -> ps: subl helloworld.rs # 本章以后使用 subl 代替 notepad +> ps: mkdir ~/Doing +> ps: cd ~/Doing +> ps: notepad helloworld.rs # 作者偏向于使用 sublime 作为编辑器 +> ps: subl helloworld.rs # 本章以后使用 subl 代替 notepad 注意这里用的后缀名是.rs,一般编程语言的代码文件都有惯用的后缀名,比如: C语言是.c,java是.java,python是.py等等,**请务必记住Rust语言的惯用后缀名是.rs**(虽然用别的后缀名也能通过rustc的编译)。 @@ -26,13 +26,13 @@ fn main() { - 编译 helloworld.rs 文件 -> ps: rustc helloworld.rs -> ps: rustc helloworld.rs -O # 也可以选择优化编译 +> ps: rustc helloworld.rs +> ps: rustc helloworld.rs -O # 也可以选择优化编译 - 运行程序 -> ps: ./helloworld.exe # windows 平台下需要加 .exe 后缀 -> Hello World! +> ps: ./helloworld.exe # windows 平台下需要加 .exe 后缀 +> Hello World! 没有`ps:`前缀的表示为控制台打印输出。 @@ -53,20 +53,20 @@ fn main() { - 查看目录结构 -> ps: tree # win10 powershell 自带有 tree 查看文件目录结构的功能 -> └─hellorust +> ps: tree # win10 powershell 自带有 tree 查看文件目录结构的功能 +> └─hellorust > ----└─src 这里显示的目录结构,在hellorust目录下有 src 文件夹和 Cargo.toml 文件,同时这个目录会初始化为 git 项目 - 查看Cargo.toml文件 -> ps: cat Cargo.toml -> [package] -name = "hellorust" -version = "0.1." +> ps: cat Cargo.toml +> [package] +name = "hellorust" +version = "0.1." authors = ["YourName "] -> [dependencies] +> [dependencies] - 编辑src目录下的main.rs文件 @@ -90,9 +90,9 @@ fn main() { - 编译和运行 -> ps: cargo build -> ps: cargo build --release # 这个属于优化编译 -> ps: ./target/debug/hellorust.exe -> ps: ./target/release/hellorust.exe # 如果前面是优化编译,则这样运行 -> ps: cargo run # 编译和运行合在一起 -> ps: cargo run --release # 同上,区别是是优化编译的 +> ps: cargo build +> ps: cargo build --release # 这个属于优化编译 +> ps: ./target/debug/hellorust.exe +> ps: ./target/release/hellorust.exe # 如果前面是优化编译,则这样运行 +> ps: cargo run # 编译和运行合在一起 +> ps: cargo run --release # 同上,区别是是优化编译的 diff --git a/quickstart/trait.md b/quickstart/trait.md index fb27120..1c9b106 100644 --- a/quickstart/trait.md +++ b/quickstart/trait.md @@ -202,4 +202,6 @@ impl Graph for SimpleGraph { let graph = SimpleGraph; let object = Box::new(graph) as Box>; + ``` + diff --git a/rcarc/rcarc.md b/rcarc/rcarc.md index 9b1b27f..5f0e4c9 100644 --- a/rcarc/rcarc.md +++ b/rcarc/rcarc.md @@ -96,13 +96,11 @@ use std::rc::Rc; struct Owner { name: String - // ...other fields } struct Gadget { id: i32, owner: Rc - // ...other fields } fn main() { From dac46df2d52d2a6ead06516de5df2ebc420744ef Mon Sep 17 00:00:00 2001 From: wayslog Date: Thu, 5 May 2016 01:31:53 +0800 Subject: [PATCH 2/2] add back build status blank --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 4542582..412a1c0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # RustPrimer +[![build status][build-badge]][build-url] + +[build-badge]: https://api.travis-ci.org/rustcc/RustPrimer.svg +[build-url]: https://travis-ci.org/rustcc/RustPrimer The Rust primer for beginners. 给初学者的Rust中文教程。