Skip to content

Commit

Permalink
Merge pull request #1 from lk-chen/patch-2
Browse files Browse the repository at this point in the history
Patch 2
  • Loading branch information
lkchen committed Jun 1, 2016
2 parents 3627c17 + 2e73e22 commit 1d3e3f4
Show file tree
Hide file tree
Showing 30 changed files with 275 additions and 144 deletions.
1 change: 1 addition & 0 deletions 1st-glance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Rust 运行在以下操作系统上:Linux, OS X, Windows, FreeBSD, Android, iO
- [MarisaKirisame(帅气可爱魔理沙)](https://github.com/MarisaKirisame)
- [Liqueur Librazy](https://github.com/Librazy)
- [Knight42](https://github.com/knight42)
- [Ryan Kung](https://github.com/ryankung)

等。在此,向他们的辛苦工作和无私奉献表示尊敬和感谢!

Expand Down
5 changes: 3 additions & 2 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* [Linux](install/install_rust_on_linux.md)
* [Mac](install/install_rust_on_mac_os.md)
* [Windows](install/install_rust_on_windows.md)
* [版本管理工具: multirust](install/multirust.md)
* [版本管理工具: rustup](install/rustup.md)
* [编辑器](editors/preface.md)
* [前期准备](editors/before.md)「wayslog」
* [vim](editors/vim.md)「wayslog」
Expand All @@ -20,7 +20,7 @@
* [变量绑定与原生类型](quickstart/primitive-type.md)
* [数组、动态数组和字符串](quickstart/vector-string.md)
* [结构体与枚举](quickstart/struct-enum.md)
* [操作流](quickstart/control-flow.md)
* [控制流](quickstart/control-flow.md)
* [函数与方法](quickstart/function-method.md)
* [特性](quickstart/trait.md)
* [注释与文档](quickstart/comments-document.md)
Expand Down Expand Up @@ -64,6 +64,7 @@
* [模块 module 和包 crate](module/module.md)
* [Prelude](module/prelude.md)
* [Option、Result与错误处理](error-handling/option-result.md)「JohnSmithX」
* [输入与输出](io/io.md)「tennix」
* [宏系统](macro/macro.md)「tennix」
* [堆、栈与Box](heap-stack/heap-stack.md)「tennix」
* [几种智能指针](rcarc/preface.md)「daogangtang」
Expand Down
6 changes: 2 additions & 4 deletions any/any.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Any和反射

熟悉Java的同学肯定对Java的反射能力记忆尤新,同样的,Rust也提供了运行时反射的能力。但是,这里有点小小的不同,因为 Rust 不带 VM 不带 Runtime ,因此,其提供的反射更像是一种编译时反射。
熟悉Java的同学肯定对Java的反射能力记忆犹新,同样的,Rust也提供了运行时反射的能力。但是,这里有点小小的不同,因为 Rust 不带 VM 不带 Runtime ,因此,其提供的反射更像是一种编译时反射。

因为,Rust只能对 `'static` 生命周期的变量(常量)进行反射!

Expand All @@ -11,10 +11,8 @@
这下可坏了……Rust不支持重载啊!于是有人就很单纯的写了两个函数~~!

其实不用……我们只需要这么写……
* 只能在nightly下编译通过

```rust
#![feature(vec_push_all)]
use std::any::Any;
use std::fmt::Debug ;

Expand All @@ -27,7 +25,7 @@ fn load_config<T:Any+Debug>(value: &T) -> Vec<String>{
};

match value.downcast_ref::<Vec<String>>() {
Some(v) => cfgs.push_all(&v),
Some(v) => cfgs.extend_from_slice(&v),
None =>(),
}

Expand Down
7 changes: 6 additions & 1 deletion book.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"lang":"zh-cn"
"lang":"zh-cn",
"pluginsConfig": {
"theme-default": {
"showLevel": true
}
}
}
6 changes: 3 additions & 3 deletions coding-style/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## 空白

* 每行不能超出99个字符。
* 缩进用个空格,不用TAB。
* 缩进只用空格,不用TAB。
* 行和文件末尾不要有空白。

### 空格
Expand Down Expand Up @@ -37,7 +37,7 @@ Point { x: 0.1, y: 0.3 }

### 折行

* 对于多行的函数签名,每一新行一个和第一个参数对齐。允许每行多个参数:
* 对于多行的函数签名,每个新行和第一个参数对齐。允许每行多个参数:

``` rust
fn frobnicate(a: Bar, b: Bar,
Expand All @@ -55,7 +55,7 @@ fn foo<T: This,
}
```

* 多行函数调用一般遵循和签名同意的规则。然而,如果最后的参数开始了一个语句块,块的内容可以开始一个新行,缩进一层:
* 多行函数调用一般遵循和签名统一的规则。然而,如果最后的参数开始了一个语句块,块的内容可以开始一个新行,缩进一层:

``` rust
fn foo_bar(a: Bar, b: Bar,
Expand Down
9 changes: 4 additions & 5 deletions collections/vec.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

## 特性及声明方式

和我们之前接触到的Array不同,`Vec`具有动态的添加和删除元素的能力,并且能够以`O(1)`的效率进行随机访问。同时,对其尾部进行push或者pop操作的效率也是`O(1)`的。
和我们之前接触到的Array不同,`Vec`具有动态的添加和删除元素的能力,并且能够以`O(1)`的效率进行随机访问。同时,对其尾部进行push或者pop操作的效率也是平摊`O(1)`的。
同时,有一个非常重要的特性(虽然我们编程的时候大部分都不会考量它)就是,Vec的所有内容项都是生成在堆空间上的,也就是说,你可以轻易的将Vec move出一个栈而不用担心内存拷贝影响执行效率——毕竟只是拷贝的栈上的指针。

另外的就是,`Vec<T>`中的泛型`T`必须是`Sized`的,也就是说必须在编译的时候就知道存一个内容项需要多少内存。对于那些在编译时候大小的项(函数类型等),我们可以用`Box`将其包裹,当成一个指针。
另外的就是,`Vec<T>`中的泛型`T`必须是`Sized`的,也就是说必须在编译的时候就知道存一个内容项需要多少内存。对于那些在编译时候未知大小的项(函数类型等),我们可以用`Box`将其包裹,当成一个指针。

### new
我们可以用`std::vec::Vec::new()`的方式来声明一个Vec。
Expand All @@ -15,7 +15,7 @@
let mut v1: Vec<i32> = Vec::new();
```

这里需要注意的是,`new`函数并没有提供一个能显式规定其泛型类型的参数,也就是说,上面的代码能根据`v1`的类型自动推倒出`Vec`的泛型;但是,你不能写成如下的形式:
这里需要注意的是,`new`函数并没有提供一个能显式规定其泛型类型的参数,也就是说,上面的代码能根据`v1`的类型自动推导出`Vec`的泛型;但是,你不能写成如下的形式:

```rust
let mut v1 = Vec::new::<i32>();
Expand Down Expand Up @@ -89,7 +89,7 @@ for i in v { .. } // 获得所有权,注意此时Vec的属主将会被转移

### push的效率研究

前面说到,`Vec`有两个`O(1)`的方法,分别是`pop``push`,它们分别代表着将数据从尾部弹出或者装入。理论上来说,因为`Vec`是支持随机访问的,因此推送效率应该是一致的。但是实际上,因为Vec的内部存在着内存拷贝和销毁,因此,如果你想要将一个数组,从零个元素开始,一个一个的填充直到最后生成一个非常巨大的数组的话预先为其分配内存是一个非常好的办法。
前面说到,`Vec`有两个`O(1)`的方法,分别是`pop``push`,它们分别代表着将数据从尾部弹出或者装入。理论上来说,因为`Vec`是支持随机访问的,因此`push`效率应该是一致的。但是实际上,因为Vec的内部存在着内存拷贝和销毁,因此,如果你想要将一个数组,从零个元素开始,一个一个的填充直到最后生成一个非常巨大的数组的话预先为其分配内存是一个非常好的办法。

这其中,有个关键的方法是reserve。

Expand Down Expand Up @@ -136,7 +136,6 @@ time spend: Duration { secs: 0, nanos: 24979520 }

注意消耗的时间的位数。可见,在去除掉debug版本的调试信息之后,是否预分配内存消耗时间降低了一倍!


这样的成绩,可见,预先分配内存确实有助于提升效率。

有人可能会问了,你这样纠结这点时间,最后不也是节省在纳秒级别的么,有意义么?当然有意义。
Expand Down
6 changes: 3 additions & 3 deletions concurrency-parallel-thread/thread.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
并发是什么?引用Rob Pike的经典描述:
> 并发是同一时间应对多件事情的能力
其实在我们身边就有很多并发的事情,比如一边上课,一边发短信;一边给小孩喂奶,一边看电视,只要你细心留意,就会发现许多类似的事。相应地,在软件的世界里,我们也会发现这样的事,比如一边写博客,一边听音乐;一边看网页,一边下载软件等等。显而易见这样会节约不少时间,干更多的事。然而一开始计算机系统并不能同时处理两件事,但这明显违背满足不了我们的需要,后来慢慢提出了多进程,多线程的解决方案,再后来,硬件也发展到了多核多CPU的地步。在硬件和系统底层对并发地支持也来越大,相应地,各大编程语言也对并发处理提供了强力的支持,作为新兴语言的Rust,自然也支持并发编程。那么本章就将引领大家一览Rust并发编程的相关知识,从线程开始,逐步尝试进行数据交互,同步协作,最后进入到并行实现一步一步揭开Rust并发编程的神秘面纱。由于本书主要面向的是Rust语言的使用,所以本章不会对并发编程相关理论知识进行全面而深入地探讨要真那样地话,一本书都不够介绍的,而是更侧重于介绍用Rust语言怎么实现基本的并发。
其实在我们身边就有很多并发的事情,比如一边上课,一边发短信;一边给小孩喂奶,一边看电视,只要你细心留意,就会发现许多类似的事。相应地,在软件的世界里,我们也会发现这样的事,比如一边写博客,一边听音乐;一边看网页,一边下载软件等等。显而易见这样会节约不少时间,干更多的事。然而一开始计算机系统并不能同时处理两件事,这明显满足不了我们的需要,后来慢慢提出了多进程,多线程的解决方案,再后来,硬件也发展到了多核多CPU的地步。在硬件和系统底层对并发的支持也来越多,相应地,各大编程语言也对并发处理提供了强力的支持,作为新兴语言的Rust,自然也支持并发编程。那么本章就将引领大家一览Rust并发编程的相关知识,从线程开始,逐步尝试进行数据交互,同步协作,最后进入到并行实现一步一步揭开Rust并发编程的神秘面纱。由于本书主要介绍的是Rust语言的使用,所以本章不会对并发编程相关理论知识进行全面而深入地探讨——要真那样地话,一本书都不够介绍的,而是更侧重于介绍用Rust语言怎么实现基本的并发。

首先会介绍线程的使用,线程是基本的执行单元,其重要性不言而喻,Rust程序就是由一堆线程组成的。在当今多核多CPU已经普及的情况下,各种大数据分析和并行计算又让线程焕发出了更耀眼的光芒。如果对线程不甚了解,请先参阅操作系统相关的书籍,此处不过多介绍。然后介绍一些在解决并发问题时,需要处理的数据传递和协作的实现,比如消息传递,同步和共享内存。最后简要介绍Rust中并行的实现。
首先我们会介绍线程的使用,线程是基本的执行单元,其重要性不言而喻,Rust程序就是由一堆线程组成的。在当今多核多CPU已经普及的情况下,各种大数据分析和并行计算又让线程焕发出了更耀眼的光芒。如果对线程不甚了解,请先参阅操作系统相关的书籍,此处不过多介绍。然后介绍一些在解决并发问题时,需要处理的数据传递和协作的实现,比如消息传递,同步和共享内存。最后简要介绍Rust中并行的实现。

## 24.1 线程创建与结束
线程对大家而言,相信一点也不陌生,在当今多CPU多核已经普及的情况下,大数据分析与并行计算都离不开它,几乎所有的语言都支持它,整个执行程序都是由一堆线程所组成。既然如此重要,接下来我们就先来看一下在Rust中如何创建一个线程,然后线程又是如何结束的。
相信线程对大家而言,一点也不陌生,在当今多CPU多核已经普及的情况下,大数据分析与并行计算都离不开它,几乎所有的语言都支持它,所有的进程都是由一个或多个线程所组成的。既然如此重要,接下来我们就先来看一下在Rust中如何创建一个线程,然后线程又是如何结束的。

Rust对于线程的支持,和`C++11`一样,都是放在标准库中来实现的,详情请参见[`std::thread`](https://doc.rust-lang.org/std/thread/index.html),好在Rust从一开始就这样做了,不用像C++那样等呀等。在语言层面支持后,开发者就不用那么苦兮兮地处理各平台的移植问题。通过Rust的源码可以看到,`std::thread`其实就是对不同平台的线程操作的封装,相关API的实现都是调用操作系统的API来实现的,从而提供了线程操作的统一接口。对于我而言,能够这样简单快捷地操作原生线程,身上的压力一下轻了不少。

Expand Down
10 changes: 5 additions & 5 deletions data-structure/stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
## 栈的实现步骤:

- [x] 1. 定义一个栈结构`Stack`
- [x] 2. 定义组成栈结构的栈点`StackNode`
- [x] 3. 实现栈的初始化函数`new( )`
- [x] 4. 实现进栈函数`push( )`
- [x] 5. 实现退栈函数`pop( )`
- 定义一个栈结构`Stack`
- 定义组成栈结构的栈点`StackNode`
- 实现栈的初始化函数`new( )`
- 实现进栈函数`push( )`
- 实现退栈函数`pop( )`

## 定义一个栈结构`Stack`

Expand Down
4 changes: 2 additions & 2 deletions editors/before.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ racer是一个由rust的爱好者提供的rust自动补全和语法分析工具

```bash
sudo /usr/local/bin/cargo install --git 'https://github.com/phildawes/racer.git'
注:现已更新为: cargo install racer
# 注:现已更新为: cargo install racer
```

来安装最新版的racer。(注:windows版的请大家补充,笔者还没有真正实践过。)
Expand Down Expand Up @@ -58,7 +58,7 @@ export RUST_SRC_HOME=/path/to/your/rust/source/
export RUST_SRC_PATH=$RUST_SRC_HOME/src
```

而Windows用户请在你的环境变量里增加两个环境变量: `RUST_SRC_HOME``你的源码文件解压路径``RUST_SRC_PATH``%RUST_SRC_HOME%\src\`
而Windows用户请在你的环境变量里增加两个环境变量: `RUST_SRC_HOME``你的源码文件解压路径``RUST_SRC_PATH` `%RUST_SRC_HOME%\src\`

### 测试

Expand Down
4 changes: 2 additions & 2 deletions editors/spacemacs.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Spacemacs
spacemacs,是一个给vimer的emacs
spacemacs,是一个给vimer的Emacs
## 简介
spacemacs是一个专门给那些习惯vim的操作,同时又向往emacs的扩展能力的人。它非常适合我这种折腾过vim,配置过emacs的人,但同时也欢迎任何没有基础的新人使用。简单来说,它是一个开箱即用的Emacs!这对一个比很多人年龄都大的软件来说是一件极其不容易的事情。

Expand All @@ -10,7 +10,7 @@ spacemacs是一个专门给那些习惯vim的操作,同时又向往emacs的扩

*nix系统中,都不一定会默认安装了Emacs,就算安装了,也不一定是最新的版本。在这里,我强烈建议各位卸载掉系统自带的Emacs,因为你不知道系统给你安装的是个什么奇怪的存在,最遭心的,我碰见过只提供阉割版Emacs的linux发行版。

建议各位自己去emacs项目主页下载emacs-24.5(本书写作时的最新版)极其以上版本,然后下载下来源码。至于emacs的安装也非常简单,linux平台老三步。
建议各位自己去emacs项目主页下载Emacs-24.5(本书写作时的最新版)极其以上版本,然后下载下来源码。至于Emacs的安装也非常简单,linux平台老三步。
```bash
./configure
make
Expand Down
8 changes: 4 additions & 4 deletions editors/vim.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# VIM/GVIM安装配置
# vim/GVim安装配置

本文是VIM的Rust支持配置,在阅读本文之前,我们假定你已经拥有了一个可执行的rustc程序,并编译好了racer。
本节介绍vim的Rust支持配置,在阅读本节之前,我们假定你已经拥有了一个可执行的rustc程序,并编译好了racer。

## 我的vim截图

Expand Down Expand Up @@ -78,7 +78,7 @@ let $RUST_SRC_PATH="<path-to-rust-srcdir>/src/"

#### 使用 YouCompleteMe

YouCompleteMe 是 Vim 下的智能补全插件, 支持 C-family, Python, Rust 等的语法补全, 整合了多种插件, 功能强大. Linux 各发行版的官方源里基本都有软件包, 可直接安装. 如果有需要进行编译安装的话, 可参考[官方教程](https://github.com/Valloric/YouCompleteMe#installation)
YouCompleteMe 是 vim 下的智能补全插件, 支持 C-family, Python, Rust 等的语法补全, 整合了多种插件, 功能强大. Linux 各发行版的官方源里基本都有软件包, 可直接安装. 如果有需要进行编译安装的话, 可参考[官方教程](https://github.com/Valloric/YouCompleteMe#installation)

让 YCM 支持 Rust 需要在安装 YCM 过程中执行 ./install.py 时加上 --racer-completer, 并在 .vimrc 中添加如下设置
```
Expand All @@ -103,7 +103,7 @@ inoremap <leader>; <C-x><C-o>
![此处应该有第二张截图](../image/editor-vim-welldone.png)

### 额外的
Q1. 颜色好搓
Q1. 颜色好挫

A1. 我推荐一个配色,也是我自己用的 [molokai](https://github.com/tomasr/molokai)

Expand Down
8 changes: 4 additions & 4 deletions error-handling/option-result.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 17.错误处理
错误处理是保证程序健壮性的前提,在编程语言中错误处理的方式大致分为两种:抛出异常(exceptions)和作为值返回。

**Rust**将错误作为值返回并且提供了原生的优雅的错误处理方案。
**Rust** 将错误作为值返回并且提供了原生的优雅的错误处理方案。

熟练掌握错误处理是软件工程中非常重要的环节,让我一起来看看**Rust**展现给我们的错误处理艺术。

Expand Down Expand Up @@ -32,7 +32,7 @@ enum Option<T> {
Some(T),
}
```
**Option**是Rust的系统类型,用来表示值不存在的可能,这在编程中是一个好的实践,它强制**Rust**检测和处理值不存在的情况。例如:
**Option** 是Rust的系统类型,用来表示值不存在的可能,这在编程中是一个好的实践,它强制**Rust**检测和处理值不存在的情况。例如:
```rust
fn find(haystack: &str, needle: char) -> Option<usize> {
for (offset, c) in haystack.char_indices() {
Expand All @@ -54,7 +54,7 @@ fn main() {
}
}
```
**Rust**使用模式匹配来处理返回值,调用者必须处理结果为`None`的情况。这往往是一个好的编程习惯,可以减少潜在的bug。**Option**包含一些方法来简化模式匹配,毕竟过多的`match`会使代码变得臃肿,这也是滋生bug的原因之一。
**Rust** 使用模式匹配来处理返回值,调用者必须处理结果为`None`的情况。这往往是一个好的编程习惯,可以减少潜在的bug。**Option** 包含一些方法来简化模式匹配,毕竟过多的`match`会使代码变得臃肿,这也是滋生bug的原因之一。

#### unwrap
```rust
Expand Down Expand Up @@ -402,4 +402,4 @@ fn file_double_verbose<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {

### 总结

熟练使用`Option``Result`是编写**Rust**代码的关键,**Rust**优雅的错误处理离不开值返回的错误形式,编写代码时提供给使用者详细的错误信息是值得推崇的。
熟练使用`Option``Result`是编写 **Rust** 代码的关键,**Rust** 优雅的错误处理离不开值返回的错误形式,编写代码时提供给使用者详细的错误信息是值得推崇的。
Loading

0 comments on commit 1d3e3f4

Please sign in to comment.