Rust
我觉得 Rust Book 第二版有些内容都缺了,
比如 Universal functional call syntax


安装
	使用 rustup


编译
	$ rustc xxx.rs
	$ ./xxx


Cargo
	用于处理项目依赖等

	创建新项目
		$ cargo new hello-cargo

	编译
		$ cargo build [--release]
			编译, 默认是 debug 版本
		$ cargo run
			编译并且运行
		$ cargo check
			检查错误
		$ cargo update
			更新依赖

	设置
		所有项目配置, 包括项目依赖, 都在 Cargo.toml 中

		增加依赖, 在 Cargo.toml 中加入
			[dependencies]
			rand = "0.3.14"
		使用 SemVer
		实际上是只要和 0.3.14 兼容即可, 如 0.3.x, x >= 14


语言基础
	区分大小写. 语句需要分号结尾. 注释是 //.
	使用 snake_case.
	/// 是文档注释, 其中支持 markdown 语法.

	变量常量声明
		声明变量如
			let x = 233;
		不必须, 但是可以指定类型如
			let x: u8 = 233;
		rust 中变量默认是不可变的, 除非
			let mut x = 233;
		注意 _ 不能作为变量名

		新变量可以用旧变量的名字 (shadowing), 新的声明会覆盖旧的.

		在任何作用域中都可以声明常量, 必须指定类型
			const CONST: u32 = 65_534;

		还可以声明全局变量, 也是任何作用域中均可, 最好指定类型
			static N: i32 = 5;

		函数内部用 let 声明的变量都放到栈上, 因此需要是定长的.

	表达式
		表达式可以有副作用
			let x = { println!(x); fac(10) };
		语句块可以复杂如
			let m = if x < y { x } else { y };
		甚至
			let x = {
					let (mut a, mut b) = (1, 1);
					loop {
							b = a+b; a = b-a;
							if b > MAX { break b; }
					}
			};

	语句
		if 语句
			if x > y {
				println!("x greater than y");
			} else if x < y {
				println!("x less than y");
			} else {
				println!("x equal to y");
			}
		loop 语句
			loop {
				// 相当于 while (1), 用 break 跳出
				// break 后可以加一个值作为语句块的返回值
			}
		while 语句
			while x != 0 {
				x = x-1;
			}
		for 语句
			for i in (1..10) {
				s = s+i;
			}
			其中 (1..10) 是 std::ops::Range<{Integer}>

			let a = [1, 2, 3, 4, 5];
			for (i, v) in a.iter().enumerate() {
				s = s+v;
			}

	函数
		声明函数格式如
			fn main() { println!("Hello world"); }

		返回值和参数格式如
			fn add(x: u32, y: u32) -> u32 { return x + y; }

		可以省略 return
			fn add(x: u32, y: u32) -> u32 { x + y }

			fn ask_for_money(x: u32) -> String {
				if x > 100 {
					String::from("Too much!")
				} else if x > 10 {
					return String::from("Emmmm...");
				} else {
					String::from("Ok")
				}
			}

		有些函数没有返回值 (diverging functions), 写成
			fn diverge() -> ! { loop { } }

	类型
		i8, u8, ..., i32, ..., i64, u64, i128, u128;
		isize, usize
			整数默认是 i32.
			字面量如 233, 547, b'A', 65_536, 0xDEADBEEF
			整数溢出在 debug 情况下是 panic, release 情况下是 wrap
		f32, f64
			默认是 f64
		bool
			取值为 true false
		char
			特别注意 rust 中 char 是 unicode 而非 ANSI
			所以可以 let ch: char = '你'.
			对于 ANSI 可以处理如 let ansichar: u8 = b'A'
		元组
			声明如 let tup: (i32, u8) = (500, b'A');
			可以解构如 let (x, y, z) = tup;
			访问某元素如 let x = tup.0;
		数组
			声明如 let a: [i32; 5] = [1, 2, 3, 4, 5];
			访问某元素如 a[0], 越界导致运行时的 panic
		Rust 有类似 typedef 的类型别名, 使用 type alias = original, 如
			type Num = i32;
			let x: i32 = 5;
			let y: Num = 5;

Ownership
	除了 GC 以外另一种保证内存安全的方案,
	检查都在编译时完成, 运行时没有开销.

	基本思想
		每个值在任何时刻都有一个且只有一个 owner 变量 (或者名字)
		不同的时候 owner 变量可能变化.
		当 owner 离开其生命周期 (e.g. 离开作用域) 的时候, 值被解构 (drop).

	移动语义
		如下代码片段中
			let x = String::from("Hi"); // A
			let y = x; // B
		1. A 语句执行了创建一个 String 值, 以及把这个值绑定到变量 x 的工作.
		2. A 执行完之后, x 是 "Hi" 的 owner, 可以通过 x 来访问这个值.
		3. B 语句执行了将 x 拥有的值转交给 y 的工作,
			执行之后 x 就不再拥有 "Hi" 了, 不能再使用没有任何值的 x

		但如下代码片段中
			let x = String::from("Hi"); // A
			let y = x.clone(); // B
		1. B 语句执行的是, 创建新的 String 值, 等于 "Hi"
			(但是和 x 拥有的 "Hi" 是不同的对象) 然后将新的值绑定给 y
		2. 之后既可以使用 x 也可以使用 y.
		具体的原因是, String 实现了 Clone trait.

		但如下代码片段中
			let x = 233; // A
			let y = x; // B
		1. B 语句之后 x 和 y 都可以用, 而且显然的改变 x 不会影响 y
		具体的原因是, 基础类型如 i32 实现了 Copy trait.

		另外, 如果将某个 String 变量作为参数传递给了 fn take_own(s: String)
		那么其值的 owner 就变成了函数的参数, 原来的变量就失去了值

	引用
		使用某个值但是不取得其 ownership (borrowing). 如
			let x = String::from("Hi");
			let y: &String = &x;
		可以使用引用作为函数参数
			fn strlen(s: &String) -> usize { s.len() }
		引用默认是不可变的, 除非使用 &mut
			fn change(s: &mut String) { s.push_str("changed"); }

		防止数据竞争, 任何时候对于任何值, 有如下情况
			1. 有单个写引用
			2. 有零或多个读引用

	slice
		除了普通引用, 还有种引用是 slice.
		slice 引用数组 / 字符串的一部分, 但是也不取得数据的 ownership.
		因此 slice 只能在其引用形式下存在.

		slice 只包含 <beg,len>; 不包含 cap (没有存储, 没有 ownership).
		slice 声明类似
			let s = String::from("abcdefgh");
			let s1 = &s[0..4];
			let s2 = &s[0..=4];
			let s3 = &s[..4];
			let s4 = &s[4..];
			let s5 = &s[..];
		字符串字面量, 以及上面的 s1 .. s5 的类型都是 &str

		slice 包括的不仅仅是字符串, 还有数组, 如
			let a = [1, 2, 3, 4, 5];
			let slice: &[i32] = &a[1..3];


结构体
	结构体的声明如
		struct Person { name: String, age: u8, }

	实例化不用 new
		let tom: Person = Person { name: String::from("Tom"), age: 17 };

	访问某个域通过点记号
		println!("{}", tom.name);

	实例化的时候可以有一些简写, 如变量名和域名相同
		let (name, age) = (String::from("Sav"), 21);
		let sav = Person { name, age }
	可以复用另外实例的域
		let tim = Person { name: String::from("Tim"), ..sav }

	元组 struct 的各个域没有名字, 但是整个 struct 是有名的
		struct ColorRGB(i32,  i32,  i32);
		let red = ColorRGB(255, 0, 0);
		println!("{}", red.0);
	通常用来给一种 tuple 起名, 防止其和普通的 tuple 混淆

	空 struct 可以用 struct Empty { } 或者 struct Empty();

	在 struct 定义寸前加上 #[derive(Debug)], 让 struct 能被 pretty print
	打印使用 println!("{:?}", some_instance);


方法
	方法的第一个参数是 self, 表示调用方法的结构体实例.

	方法在 impl 块定义, 一个结构体可以有多个 impl 块
		impl Person {
			fn age_of_next_year(&self) -> u8 { self.age + 1 }
		}
	调用如
		println!("{}", tom.age_of_next_year());

	第一个参数不是 self 的方法是静态方法, 如
		impl Person {
			fn new(name: String, age: u8) -> Self {
				Person { name, age }
			}
		}
	其中 Self 是实现方法的类型, 通常就是 self 的类型.
	调用类似
		Person::new(String::from("Tom"), 12)


Trait
	类似 Java 的 interface.

	定义如
		trait Summary {
			fn summarize(&self) -> String;
		}
	在定义中不要忘记写 self

	结构体在单个 impl 块中实现某 trait 的所有接口
	格式使用 impl TRAIT for STRUCT, 如
		struct NewsArticle { ... }
		impl Summary for NewsArticle {
			fn summarize(&self) -> String {
				// ...
			}
		}

	trait 中的方法可以有默认实现,
	这时实现 trait 的结构体就不一定要重写默认的实现
		trait Summary {
			fn summarize(&self) -> String {
				return String::from("stupid summary");
			}
		}

	函数的参数可以是 trait, 类似接口参数, 使用 impl 关键字
		fn notify(x: impl Summary) { ... }
	可以用泛型写成等价的
		fn notify<T: Summary>(x: T, y: T) { ... }
	以及
		fn nofity(x: T, y: T) where T: Summary { .. }
	注意 impl TYPE 只能在函数参数或者返回值处使用

	并且一个函数可以要求参数实现多个 trait
		pub fn notify(x: impl T) where T: Summary + Copy { ... }
	甚至函数返回可以是 trait
		pub fn return_trait() -> impl Summary { ... }

	如果结构体实现不同的 trait 中同名函数, 直接调用会有歧义
		struct Foo;
		impl Bar for Foo {
			fn f(a: i32) { println!("Bar::f({})", a); } 
		}
		impl Baz for Foo {
			fn f(a: i32) { println!("Baz::f({})", a); } 
		}
	需要使用方法调用的一般语法
		let f = Foo;
		Bar::f(&f, 2);
		Baz::f(&f, 3);

Derivable traits
	使用简单的一行属性, 使得结构体实现某 trait, 如
		#[derive(Debug, Copy, Clone)]

	常用的 derivable traits 有
		Debug
			允许可读输出
		PartialEq
			允许 == 和 != 比较结构体.
			结构体相同, 当且仅当所有字段相同
		Eq
			是一个 marker trait, 语义是对于这个类型的所有值, 它都等于自己
			Eq 依赖于 PartialEq, 但是并不等价.
			如对于浮点, NaN != NaN
		PartialOrd
			允许 < > <= >=
			依赖于 PartialEq.
			对于结构体, 从前到后比较每一字段.
			对于 enum, 前面的更小.
		Ord
			全序, 相对于 PartialOrd 的偏序.
		Clone
			可以完成 (可能很昂贵的, 可能拷贝堆数据) 深拷贝
		Copy
			只复制栈上的值就可以完成拷贝, 如 i32
		Hash
			可以被散列, e.g. 作为 Map 的 K
		Default
			某个类型的默认值.


泛型
	允许变量的类型是抽象的类型, 待使用时再确定.
	Rust 的泛型实现 monomorphization 类似 C++ 的 template,
	没有运行时开销.

	泛型函数如
		fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
			let mut largest = list[0];
			for &item in list.iter() {
				if item > largest {
					largest = item;
				}
			}
			largest
		}

	泛型结构体如
		struct Point<T> { x: T, y: T, }
	之后声明变量如
		let p = Point { 1, 2 };

	泛型结构体的 impl 块如
		impl<T> Point<T> {
			fn get_x(&self) -> &T { &self.x }
		}
	注意 impl 块中, 要写 impl<T> 而非 impl, 否则就是泛型特化的写法了如
		impl Point<i32> {
			// ...
		}
	在特化的 impl 中可以加入新方法, 表示这些方法只有对于部分的 T 才存在
		impl Point<i32> {
			fn only_work_with_i32() { ... }
		}

	即使在泛型的 impl 块中, 方法也可以有泛型参数
		impl <T> Point<T> {
			fn foobar<U>(&self, v: U) -> (T, U) { (self.x, v) }
		}

	还可以有泛型 enum, 如
		enum Result<T, E> {
			Ok(T),
			Err(E),
		}


面向对象特性
	封装
		struct 的字段, 函数, 除非标记为 pub, 否则总是私有的.

	继承
		Rust 没有继承, 而是使用 trait object 完成类似的功能.

	trait 对象指向一个实现了该 trait 的值, 它是一个指针, 如 & 和 Box<>
	任何实现了该 trait 的值都可以是一个 trait object.
	如
		let a: Vec<&dyn Animal> = vec![&Cat {color: Orange}, &Dog {male: True}]

	trait 对象有运行时的开销, 而泛型没有.
	trait 的好处在于, 它能完成 dynamic dispatch
	(多态中根据类型决定调用的函数具体是哪个), 如
		fn foobar(name: &str) -> &dyn Speaker {
				match name {
						"tom" => &Tom { age: 15 },
						"jerry" => &Jerry(),
						_ => &Tom { age: -1 },
				}
		}
	这样的代码不可能被施加 monomorphization, 不可能用泛型实现


Lifetime
	通常 lifetime 都是推导的, 但是无法推导的时候必须指定.

	基本原理是, 任何引用都不应当比其引用的值有更长的生命周期,
	否则就会出现野引用. 所有引用都有一个生命周期.
	值也有生命周期, 通常就是其 owner 的作用域.

	有些情况, 如函数返回一个引用, 结构体中有引用的时候,
	可能自动推导无法确定此引用的生命周期,
	那么需要手动增加泛型的生命周期注解.

	生命周期注解的格式类似泛型, 如
		fn longest<'a>(x: &'a str, y: &'a str): &'a str { ... }
	说明返回值的生命周期和两个参数中最短的一个是相同的.
	在结构体中, 类似
		struct StructWithRef<'a> {
			v: &'a i32,
		}
	其对应的 impl 块类似
		impl<'a> StructWithRef<'a> {
			// ...
		}

	Rust 能推导的生命周期, 如
		fn ident(a: &str) -> &str { a }
	基本规则如下
		* 如果只有一个输入 lifetime 'a e.g. 只有一个参数,
			那么所有输出的 lifetime 都是 'a
		* 如果有一个输入是 &self 或者 &mut self,
			那么所有输出的 lifetime 都是 self 的生命周期

	一个特殊的 lifetime 是 'static, 其代表程序执行的全过程.
	字面量串的 lifetime 是 'static


Enum
	枚举在 Rust 中是一种类型, 其和其他类型一样可以作为函数参数, 返回值的类型.

	基础的 enum 声明格式如
		enum IpAddrKind { V4, V6, }
	之后引用如
		let four = IpAddrKind::V4;

	枚举类型也可以有自己的域, 甚至变成结构体, 如
		enum Message {
			Quit,
			Move { dx: i32, dy: i32 },
			Write(String),
			Panic(u8, String),
		}
	之后
		let loopbackv4 = IpAddr(127, 0, 0, 1);

	枚举也可以有 impl 块
		impl Message {
			// .. methods on &self or &mut self
		}

	很有用的一个枚举类型是 Option<T> { Some(T), None }
	Option 用来代替其他语言的 null, 因为 null 容易出现错误
	注意用 None 赋值时候需要指定类型
		let absent_number: Option<i32> = None;


模式匹配结构
	模式匹配通常用于处理枚举类型, 类似 C 的 switch-case 如
		match x {
			Some(val) => println!("Got value {}", val),
			None => println!("No value found"),
		}
	其中每一项 PATTERN => EXPR 称为一个 arm,
	每个 arm 都应该由逗号结尾.
	第一个 arm 匹配所有 Some, 并且将 Some 包装的值绑定到 val 中

	对应 switch-case 的 default 的是 _, 空语句是 ()
		let y = match x {
			1 => { println!("unit val"); 1 },
			0 => { println!("zero val"); 0 },
			_ => -1,
		}

	如果只考虑多种情况的一种, 那么
		match { v => EXPR1, _ => EXPR2 }
	可以简写为 if let PATTERN = EXPR { ... } [else { ... }], 如
		if let Some(15) = opt_val {
			println!("We got a Some(15)!");
		} else {
			println!("Looking for Some(15)... failed");
		}

	Rust 中大量使用模式匹配, 如
		* match PATTERN => EXPR,
		* if let PATTERN = EXPR { ... }
		* while let PATTERN = EXPR { ... }
		* for PATTERN in EXPR { ... }
		* 甚至 let PATTERN = EXPR, 如
			let (x, y) = (15, 12)
		* 函数参数的形式是 PATTERN: EXPR 如
			fn ptn_arg(&(x, y): &(i32, i32)) { ... }

	利用 pattern matching 可以轻松地完成结构化的数据的解构, 如
		* 解构元组: let (x, y) = (4, 5)
		* 解构结构体: fn fnparam_ptn(&MyStruct {x, y}: &MyStruct) { ... }
	解构可以嵌套

	PATTERN 的形式可以很多样, 如
		match xxx {
			x1 | x2                        => // ...
			x1 ... x2                      => // ...
			Point {x: 0, y}                => // ... 这里不能用 x
			&Point {x, y}                  => // ... 如果数据是引用
			Some(x) if x < 5               => // ...
			(first, _, third, _, fifth)    => // ...
			HighDimPts { first, .., last } => // ... 使用 .. 必须是无歧义地
			_                              => // ...
		}

	PATTERN 有两种, refutable 和 irrefutable.
	诸如 _, x, (x, y) 是 irrefutable 的, 不能放到 if let 之类里面
	诸如 Some(x) 是 refutable 的, 不能直接放到 let 里面
	match arm 必须是 refutable 的, 除非最后一个 arm

	解构默认就会取得 ownership, 可以使用 ref 来避免
    let so = Some(String::from("Some ownership"));
    if let Some(ref bstr) = so { println!("one: {}", bstr); }
    if let Some(ref mut bstr) = so { so.push_str("~~~"); }
	而不能写成 if let Some(&bstr) ...

	使用 @ 来完成检测条件的同时变量绑定
		match i32tuple {
			(x @ 3...7, y) => // we can use the variables x and y here
			_ => // oth
		}


函数式编程 // TODO
	闭包
	闭包可以完成 lazy evaluation! (把值引用变成函数调用)

	定义格式
		let myclosure = |num| {
			println!("Calling myclosure({})", num);
			num + 2
		};

	闭包可以不用手动指定参数和返回值的类型, 而是可以推断
		不过要加也可以
		let myclosure = |num: i32| -> i32 {
			println!("Calling myclosure({})", num);
			num + 2
		};

	Rust 每个闭包的类型是一个独有的匿名类型.
	两个闭包即使签名相同, 类型也不会相同.

	闭包可以捕获环境中的变量, 函数不能

	closure 捕获环境变量的方式有三种
		1. 取得所有权
		2. 取得写 handle
		3. 取得读 handle
	分别对应三种 Trait:
		FnOnce
		FnMut
		Fn
	闭包默认都实现 FnOnce, 如果不获取 ownership 则实现 FnMut, 如果不修改变量则实现 Fn

	iterator
		可以 for x in xxx.iter() { ... }
		(如果实现了 IntoIterator, 还可以 for x in xxx { ... })

		Iterator 是一个 trait, 实现需要
			1. 指定一个 type Item
			2. 实现 fn next(&mut self) -> Option<Self::Item>

		let v1: Vec<i32> = vec![1, 2, 3];
		let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();

	iterator 和 closure 是 zero-cost abstraction


智能指针
	Rust 中, 引用被认为是一种指针, 也有不安全的底层指针.

	智能指针相对于引用来说, 有额外的元数据以及功能, 如引用计数.
	另外, 引用没有数据 ownership, 但是通常智能指针拥有数据 ownership.
	事实上, String 和 Vec<T> 就都是智能指针.

	Box<T>
		指针存储在栈上, 但是指向的数据在堆上.

		并且指针拥有数据的 ownership, 因此 Box<T> 离开作用域时, 会解构
			1. 栈上的指针
			2. 堆上的数据
		这种功能由 Drop trait 实现

		指针可以当成引用来使用, 如
			let b = Box::new(5);
			println!("{}", b);
		这是由 Deref trait 来实现的

		一个例子就是链表的实现
			enum List {
				Next(i32, Box<List>),
				End
			}
		这里不能直接用 List, 因为这样的话就类似
			struct List{
				int val;
				struct List next;
			}
		了, 出现无线循环.
		也不能用 &List, 因为 Next 的生命周期将变得不清楚.

	Rc<T>
		数据可能有多个 owner, 它们都离开生命周期之后数据才能被解构
		Rc<T> 不是线程安全的, 只能在单线程环境下使用.

		例子还是链表的实现, 不过这次两个链表能有相同的后缀.
			use std::rc::Rc;
			enum RcList {
					N(i32, Rc<RcList>),
					E
			}
		之后构建链表的时候用到两个函数, 取得 ownership 的 new,
		以及完成浅拷贝的 clone
			use RcList::*;
			let a = Rc::new(
							N(1, Rc::new(
							N(2, Rc::new(E)))));
			let b = N(10, Rc::clone(&a));
			let c = N(20, Rc::clone(&a));

	RefCell<T>
		Rust 中一个设计模式是 interior mutability, 基本含义是,
		修改一个值, 即使有指向该值的不可变引用.
		通常这个可以用来实现可变的字段, 即使整个值是不可变的.
		如 Rc 中的计数就是可变的字段 -- 但是它不对外暴露
		所以这个字段可变, 对于不可变的 &Rc 是完全没有问题的.

		RefCell<T> 可以实现 interior mutability, 但只能在单线程情况下使用
		方法有
			let refcell = RefCell::new(x)
				创建 RefCell
			refcell.borrow_mut()
				取得一个 x 的可变引用 &mut T
			x.borrow()
				取得一个 x 的不可变引用 &T

		RefCell 并没有逃离 Rust 的 borrow checker, 只是让检查推迟到了
		运行时而非编译时

		Rc<RefCell<T>> 可以得到支持多 owner 的可变引用, 但很不安全,
		容易产生循环引用, 造成引用计数到达不了 0 而内存泄漏

	Weak<T>
		引用计数可以分为两类, strong 和 weak,
		由引用是否有值的 ownership 决定.
		strong 计数表示, 有多少引用是拥有值的 ownership 的.
		weak 计数表示, 有多少计数是单单一个 handle 的.
		当 strong 计数到达 0 的时候, 值被解构.
		换言之, 值的解构和 weak 计数无关.

		典型例子就是循环链表, 如果 tail 到 head 的引用是 strong 引用,
		那么这个链表中元素的 strong 计数永远不会到 0, 也就出现了内存泄漏.
		但是链表暴露的应当只有 head,
		所以 tail 到 head 的引用也只是一个 handle, 不应当是 strong 引用.

		如上, tail 到 head 的引用就是 weak 引用, 用 std::rc::Weak<T> 表示
		和其他的智能指针不同, Weak 不拥有其指向值的 ownership.
		方法有
			let wk = Weak::new(x)
				创建
		如果想要使用 wk 指向的值, 必须现将其转为 strong 引用, 防止野引用
			match wk.upgrade() {
				Some(rc) => println!("{:?}", *rc),
				None => println!("the value wk points to is no longer here!")
			}
		当然, strong 引用也可以转为 weak 引用, 使用
			Rc::downgrade(this: &Rc<T>) -> Weak<T>

	Deref trait
		自定解引用算子的行为. 要求实现
			type Target;
			fn deref(&self) -> &Self::Target;

		最初 Rust 中引用不能直接访问数据, 必须使用 * 来解引用才行, 如
			fn are_same<T: PartialEq + std::fmt::Debug>(x: T, y: T) {
					println!("are_same {:?} {:?}: {}", x, y, x == y);
			}

			let x = 2;
			let y = &x;
			are_same(x, y);		// error: {integer} expected, found &{integer}
			are_same(x, *y);	// ok
			are_same(&x, y);	// ok
		实现了 Deref trait 的智能指针也能被解引用
			let z = Box::new(x);
			are_same(x, z);		// error
			are_same(x, *z);	// ok. Box<i32> derefs to i32
			are_same(&x, z);	// error
		这里 *z 实际上是 *(z.deref())

		Rust 在一些情况下可以自动帮我们添加解引用算子和取指针算子, 简化语法
		称为 dereference coercion, 如将
			1. &T to &U where T: Deref<Target=U>
			2. &mut T to &mut U
			2. &mut T to &U
		不这样做的话就会出现反面例子如 nginx 的 void ****conf_ctx
		(在 nginx-1.14.0/src/core/ngx_cycle.h:40)

	Drop trait
		智能指针用来解构自己的同时解构自己指向的数据. 要求实现
			fn drop(&mut self)
		这个方法在指针离开作用域时自动调用, 而且不能手动调用

		另外, 有时候可能需要提前调用 drop 函数, 如提前释放一个锁,
		一种方法是使用 std::mem::drop, 如
			drop(early_lock)


模块化代码 crate
	Rust 中也有模块, 创建如
		$ cargo new mymodule --lib
	这里 --lib 表示创建一个库而非可执行的项目.
	当然可执行的项目中也可以也有模块.

	定义模块使用 mod 关键字
		mod name {
			// definitions
		}
	可以嵌套模块, 如
		mod network {
			fn foobar() { }
			mod far {
				fn foobar() { }
			}
		}

	模块或者子模块的顶层源文件中可以导入其他文件的内容,
	只需要一行 mod name; 如
		// lib.rs
		mod sub;

		fn foobar() {
			println!("This is mymodule::foobar()");
		}

		// sub.rs. 这里不需要 mod sub { ... }
		fn foobar() {
			println!("This is mymodule::sub::foobar()");
		}

	子模块如果希望有自己的子模块, 如 top::sub::sub2,
	那么其应当被放到一个单独的目录下, 子模块的顶层文件是 mod.rs, 如
		// lib.rs
		mod sub;

		fn foobar() {
			println!("This is mymodule::foobar()");
		}

		// sub/mod.rs
		fn foobar() {
			println!("This is mymodule::sub::foobar()");
		}

		mod sub2;

		// sub/sub2.rs
		fn foobar() {
			println!("This is mymodule::sub::sub2::foobar()");
		}

	简单地, 若子模块没有它自己的子模块, 则放到 sub.rs 不然就 sub/mod.rs

	cargo 默认只检查 lib.rs,
	如果有其他文件, 需要使用如上方式在 lib.rs 中提及

	模块中所有符号都默认是 private, 只有加上 pub 才能被模块外代码使用, 如
		// lib.rs
		pub mod sub;

		pub fn foobar() {
			println!("This is mymodule::foobar()");
		}

	使用模块的符号
		首先需要导入模块的 crate, 通常如
			// main.rs, in the same directory as lib.rs
			extern crate mymodule;

		如果希望使用 mymodule::sub::sub2::foobar(), 可以直接使用
			mymodule::sub::sub2::foobar();

		也可以使用 use 语句
			use mymodule::sub::sub2;
			sub2::foobar();
		或者
			use mymodule::sub::sub2::foobar;
			foobar();
		以及
			use mymodule::sub::sub2::foobar as fb;
			fb();

		use 语句可以导入多个符号, 如
			use mymodule::sub::{sub2, foobar};
		或者
			use mymodule::sub::*;

		use 开始的地方是当前模块,
		所以可以直接使用兄弟姐妹的符号
			use sibling::foobar;
		而不是
			use super::sibling::foobar();

		子模块使用父模块的符号, 可以
			// sub/sub2.rs
			fn parent_foobar() {
				use super::foobar;
				foobar();
			}
		可以从顶层模块开始导入, 如
			// sub/sub2.rs
			fn root_foobar() {
				use ::foobar;
				foobar();
			}

高级 crate // TODO
	profile 包含构建的各种默认选项. 在 Cargo.toml 中设定, 如
		[profile.dev]
		opt-level = 0
		[profile.release]
		opt-level = 3


容器 // TODO
	容器的数据都存储在堆上
	Vector
		let mut v1: Vec<i32> = Vec::new();
		let mut v2 = vec![1, 2, 3];
		v1.push(3);
		let v12 = &v1[2]; // &i32
		let v12_ = v1.get(2); // Option<&i32>
		for i in &v1 {
			println!("{}", i);
		}
		for i in &mut v1 {
			*i += 20;
		}
	String
		let s1 = String::from("Hello World");
		let mut s2 = "hi!".to_string();
		s2.push_str("bad");
		s2.push('!');
		let s3 = format!("{}, {}", s1, s2);
	HashMap
		use std::collections::HashMap;
		let mut map = HashMap::new();
		map.insert(String::from("Age"), 12);
		let mut map2: HashMap<_, _> = vec![1, 2, 3].iter().zip(vec![5, 6, 7].iter()).collect();
		insert 是要取得 ownership 的, 除非传入 ref
			for (k, v) in &map {
				println!("{}, {}", k, v);
			}
			match map.get("key") {
				Some(val) => // deal with val,
				None => // ...
			}
		如单词计数
			let mut map = HashMap::new();
			for word in text.split_whitespace() {
			    let count = map.entry(word).or_insert(0); // 返回 &mut xxx
			    *count += 1;
			}


错误处理 // TODO
	错误分成可恢复和不可恢复的

	不可恢复的使用 panic
		panic!("message");
	如果需要报错的 backtrace, 应当
		$ RUST_BACKTRACE=1 cargo run

	可恢复的错误通常使用 enum Result<T, E> { Ok(T), Err(E) } 结合 match 完成
		let f = File::open("hello.txt");

		let f = match f {
			Ok(file) => file,
			Err(error) => {
				panic!("There was a problem opening the file: {:?}", error)
			},
		};

		这个可以简单地写成

		let f = File::open("hello.txt").expect("error opening file");

	如果当前函数上下文中不知道如何处理某错误, 可以向上传播
	就是把当前函数的返回值改成 Result<T, E>
	这个通常可以简写成
		fn read_hello() -> Result<String, io::Error> {
		    let mut f = File::open("hello.txt")?;
		    // ...
		}
		也可以链接
		let mut s = String::new();
		File::open("hello.txt")?.read_to_string(&mut s)?;


测试 // TODO
	测试函数是有 test 属性的
		#[test]
		fn xxx() { ... }
	其中通常使用 assert!(), assert_eq!(), assert_ne!(), panic!()
		如 assert_eq!(x1, x2, "x1 does not equal to {}", "x2");
	另外可以用 should_panic 属性来让一个测试函数通过, 如果该函数 panic
	使用 ignore 属性来让昂贵的测试默认不运行, 除非加上 --ignored
	测试使用
		$ cargo test	# 并行运行所有测试
		$ cargo test -- --test-threads=1	# 串行运行测试
		$ cargo test -- --nocapture	# 对于通过的测试也显示 stdout
		$ cargo test NAME	# 只运行 tests::*NAME* 函数 (名字中包含 NAME 的函数)


宏
	Rust 中宏的处理是在 AST 构建完成之后进行的, 因此必须是 disciplined
	宏展开之后, 是一个 AST 子树, 而且必须是
		* 模式
		* 语句
		* 表达式
		* items
		* impl items
	这样可以防止奇怪的优先级问题
	宏事实上是一个语法拓展, 不属于 Rust 语法的一部分

	使用宏的方法一般是
		$name ! $arg
	其中 $arg 是单个的 token tree (使用 "[]", "{}", "()" 组合起来的一系列 token)
	因此可以写 println!(...) 也可以写 println!{...}

	定义宏格式为
		macro_rules! $name {
			$rule0 ;
			$rule1 ;
			// ...
		}
	其中每个 rule 格式类似
		($pattern) => { $expansion }
	如
		macro_rules! four { () => { 1 + 3 } ; }
	甚至可以
		macro_rules! four { (NORMAL) => { 1 + 3 } ;
		    (BAD) => { 2 + 3 } ;
		    (FUCKING CRAZY) => { 1 - 3 } ; }
		fn main() { println!("{} {} {}", four!(NORMAL),
		    four![BAD], four!{FUCKING CRAZY});
		    // 4 5 -2
		}
	匹配宏的时候是按照从上到下第一个能匹配的来的,
	如果匹配失败就会 panic 而非继续尝试下面的 rule

	宏当然可以捕获参数, 单个捕获的格式是
		$ident:kind
	其中 kind 可以是 item (类似函数 / struct / module)
	block ({ 之间的代码 }) 以及 stmt, pat, expr, ty, ident, path, tt
	如
		macro_rules! max3 {
		    ($a:expr, $b:expr, $c:expr) => {
			if $a > $b { if $a > $c { $a } else { $c } }
			else { if $b > $c { $b } else { $c } }
		    }
		}

	参数包括重复的时候, 基本捕获的格式为
		$( REP_ITEM ) SEP REP
	SEP 为分割符, 类似 , ,, ::
	REP 为重复标记, 仅为 * (0或多个) + (至少 1 个)
	REP_ITEM 为标记每个重复项的格式
	在 $expansion 中也使用 $( ITEM ) REP 来完成重复
	可以实现简单的 vec! 如下
		macro_rules! myvec {
		    ($($a: expr),*) => 
		}
	甚至可以是
		macro_rules! foo {
		    ($(FUCK),+) => { println!("Stop FUCKING!"); } ;
		    ($a:expr) => { println!("Got expr: {}", $a); } ;
		}
		fn main() { foo!(FUCK, FUCK); foo!(FUCK); foo!(254); foo!("bad"); }


并行
	线程模型有 1:1 (语言线程对应一个内核线程), 如 pthread.
	也有 m:n 在一系列内核线程上复用多个语言线程, 如 goroutine, 称为 green thread.
	Rust 为了保证最小的 runtime, 使用 1:1 线程.

	创建线程使用 thread::spawn(), 如
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("Hi number {} from spawned", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
	这里 handle 可以用来执行 join 操作. 当 handle 被解构时, 子线程被自动 detach.

	线程可以有返回值, 使用 join 来取得线程返回值, 或者等待线程执行完成
    match handle.join() {
        Ok(t) => println!("{:?}", t),
        Err(_) => println!("thread join failed"),
    }

	线程之间的执行顺序是不确定的, 因此如果某个线程希望使用另外线程的数据,
	一般需要先取得 ownership, 如
    let v = vec![1, 2, 3];
    let handle = thread::spawn(move || {
        println!("{:?}", v);
    });
    handle.join().unwrap();

	Rust 的线程间通讯可以使用 channel 来完成, 类似 Golang
	创建 channel 如
		use std::sync::mpsc;	// multiple producer, single consumer
		let (tx, rx) = mpsc::channel();
	有多个发送者时使用 mpsc::Sender::clone
		let tx2 = mpsc::Sender::clone(&tx);

	之后发送使用 tx.send()
		match tx.send(val) {
			Ok(()) => println!("sent val"),
			Err(e) => println!("{}", e),
		}
	发送操作可以在不同的线程中执行, 就如不同的 goroutine 通过 chan 通信

	接收使用 rx.recv(), 如
		let recv_val = rx.recv().unwrap()
	recv() 是阻塞的, 使用 try_recv() 来非阻塞的检查接受
		match rx.try_recv() {
			Ok(val) => println!("recved {}", val),
			Err(e) => println!("{}", e),
		}

	rx 对象可以使用 for 遍历, 直到 chan 被关闭
		for v in rx {
			println!("rx got {}", v);
		}
	当所有 tx 被解构时, chan 自动被关闭

	除了 channel, 也可以有线程共享的资源, 如全局变量.
	这些资源需要被 Mutex<T> 保护.
	如一个被多个线程使用的全局计数器实现为
    let counter = Arc::new(Mutex::new(0));
	Mutex 提供了 interior mutability 因此这里不需要 mut

	Rust 强制要求使用被 Mutex 保护的资源前, 先用 lock() 取得锁.
	lock() 实际返回的是一个智能指针, 可以像访问其他智能指针一样访问它
	注意取得锁的先决条件时拥有这个锁的 ownership.
		let counter = Arc::clone(&counter);
		let h = thread::spawn(move || {
				let mut num = counter.lock().unwrap();
				*num += 1;
		});

	上面使用了 Arc<T>. Arc 是 Rc 的多线程版本, 基本接口和 Rc 相同.
	它使得 counter Mutex 能同时有多个 owner,
	并且在引用计数到达 0 的时候被解构.
	一个类比可以看成, Arc <=> Rc, Mutex <=> RefCell.
	而且使用 Mutex 的时候要注意可能产生死锁.

	Send trait 是一个 marker trait,
	指定某类型值的 ownership 可以在不同线程之间发送 / 共享.
	Sync trait 也是 marker trait, 
	指定不同的线程可以同时持有该类型的值的引用.
	这两个 trait 是自动实现的, 手动实现是不安全的.


Supertrait
	类似 trait 的继承, 通常用来要求实现某个 trait 的值也必须实现另外某个 trait.
	如实现 Copy 必须实现 Clone 一样.
	格式如
		trait Speaker {
			fn speak(&self);
		}

		impl Superspeaker {
			fn superspeak(&self) {
				for _  in 0..10 { self.speak(); }
			}
		}

Unsafe // TODO
	用来避免编译时的静态检测. 通常完成对内存的高级操作.

	对裸指针解引用
		裸指针类型如
			*const T
			*mut T
		裸指针不会被 borrow checker 检查,
		但是不保证有效, 也不完成自动解构.
		对裸指针的解引用是不安全的, 但是创建它们还是安全的

		创建裸指针如
			let mut v = 5;
			let r1 = &v as *const i32;
			println!("{:?}", r1);
			unsafe { println!("{:?}", *r1); }
		以及
			let r2 = &mut v as *mut i32;
			unsafe { *r2 = 15; }
			println!("{:?}", r2);
			unsafe { println!("{:?}", *r2); }
		裸指针允许同时有 mut 和 const 指向统一块内存区域

	调用不安全的函数
		在一个安全的函数中用 unsafe 来包装不安全的代码或者调用

	不加锁地修改全局变量
		使用 static 可以创建全局变量
			static GLOBVAR: &str = "Hello World";
	实现 unsafe trait

	最好应该把 unsafe 的 API 用 safe 的方式包装起来提供出去


常见操作
	类型转换
		let a = 5;
		println("{}", a as f64);

	字符串转数字
    let v: i32 = match numstr.parse() {
        Ok(v) => v,
        Err(e) => panic!(e),
    };
		必须指定 parse() 的类型