3131
3232以及基于引用的迭代器推导式宏
3333
34- # 用法
3534
36- ## 集合推导式
35+
36+ # 集合推导式
3737
3838你可以完全将集合推导式宏视为 ` for ` 循环的语法糖
3939(事实上, 这些宏就是使用 ` for ` 循环实现的)
4040所以你可以看到很多很熟悉的语法
4141不过, 他们将更加符合人体工程学, 更加便于阅读和使用
4242
43- ### 简单示例
43+ # 简单示例
4444``` rust
4545use better_comprehension :: vector;
4646let vec_1 = vec! [" AB" . to_string (), " CD" . to_string ()];
@@ -61,7 +61,7 @@ println!("{:?}", vec_2); // vec_2还活着
6161assert_eq! (vec , vec! [" 12" . to_string (), " 34" . to_string ()]);
6262```
6363
64- ### 集合推导中的 if
64+ # 集合推导中的 if
6565
6666` for ` pattern ` in ` collection ` if ` ... 将被完全翻译为
6767``` rust
@@ -72,7 +72,7 @@ for pattern in collection {
7272}
7373```
7474
75- #### if conditions 作为过滤条件
75+ ## if conditions 作为过滤条件
7676其中 conditions 为任意值为bool的表达式
7777只有当表达式返回true时, 才会将对其进行推导映射
7878``` rust
@@ -92,7 +92,7 @@ let linked_list = linked_list![ i*2 for i in 1..=3 if judge_function(i) ];
9292assert_eq! (linked_list , LinkedList :: from ([2 , 6 ]));
9393```
9494
95- #### if let 表达式
95+ ## if let 表达式
9696``` rust
9797use better_comprehension :: vector;
9898let vec_1 = vec! [Some (" 123" . to_string ()), None , Some (" 456" . to_string ())];
@@ -103,7 +103,7 @@ let vec = vector![
103103assert_eq! (vec , vec! [" 123" . to_string (), " 456" . to_string ()]);
104104```
105105
106- #### 根据条件返回不同的值
106+ # 根据条件返回不同的值
107107``` rust
108108use better_comprehension :: b_tree_set;
109109use std :: collections :: BTreeSet ;
@@ -114,7 +114,55 @@ let b_tree_set = b_tree_set!{
114114assert_eq! (b_tree_set , BTreeSet :: from ([1 , 13 ]));
115115```
116116
117- ### 使用模式匹配
117+ # let 表达式
118+ let 表达式所属的范围是它上方最近的 for in 表达式, 且受到if表达式筛选后的结果(如果有的话), 可以有多个let表达式, 他们的阅读顺序是从上到下的.
119+ 完全等价于
120+ ``` ignore
121+ for pattern in collection {
122+ if ... { // 如果有的话
123+ let ...;
124+ let ...;
125+
126+ }
127+ }
128+ ```
129+
130+ ## 使用let表达式绑定变量
131+ ``` rust
132+ use better_comprehension :: vector;
133+ let vec = vector! [
134+ b
135+ for x in 1 ..= 3 if x != 2
136+ let __x__ = x * 2
137+ for y in 4 ..= 6 if y + __x__ != 7
138+ let z = __x__ + y
139+ let a = z * 2
140+ let b = match z {
141+ 5 ..= 6 => 1 ,
142+ 7 ..= 8 => 2 ,
143+ _ => 3
144+ }
145+ ];
146+ assert_eq! (vec , vec! [1 , 2 , 3 , 3 , 3 ]);
147+ ```
148+
149+ ## 使用 let _ = 或 let () = 执行任意代码
150+ 这是一个极其强大的功能, 请谨慎使用
151+ ``` rust
152+ use better_comprehension :: vector;
153+ let vec = vector! [
154+ x
155+ for x in 1 ..= 3
156+ let _ = println! (" {}" , x )
157+ let () = {
158+ for i in 1 ..= 3 {
159+ println! (" {}" , i );
160+ }
161+ }
162+ ];
163+ ```
164+
165+ # 使用模式匹配
118166``` rust
119167use better_comprehension :: vec_deque;
120168use std :: collections :: VecDeque ;
@@ -137,7 +185,7 @@ println!("{:?}", people); // people还活着
137185assert_eq! (vec_deque , VecDeque :: from ([" Bob" . to_string ()]));
138186```
139187
140- ### 嵌套推导式
188+ # 嵌套推导式
141189和python的推导式一样, 本库的for循环是从上到下读取的.
142190
143191``` rust
@@ -160,8 +208,9 @@ assert_eq!(vec, vec![(1, 4), (1, 5), (1, 6),
160208 (3 , 4 ), (3 , 5 ), (3 , 6 )]);
161209```
162210
163- ### 使用块在返回前执行代码
211+ # 使用块在返回前执行代码
164212这是一个极其强大的功能, 你可以在返回前执行任意代码但会降低可读性, 请谨慎使用
213+ 如果可以, 更推荐使用在最后一个 ` for in ` 后 ` let _ = ` 或 ` let () = ` 执行代码来代替
165214``` rust
166215use better_comprehension :: vector;
167216let vec_1 = vec! [" 123" . to_string (), " 456" . to_string ()];
@@ -191,7 +240,7 @@ assert_eq!(
191240);
192241```
193242
194- ### 简写说明
243+ # 简写说明
195244请你注意,由于在rust中, for loop 是消耗所有权的.
196245所以通常来说, 对于多层循环, 如果你希望原容器被消耗, 你应该写成如下这样:
197246``` rust
@@ -251,7 +300,7 @@ println!("{:?}", vec_2); // work well
251300// println!("{:?}", vec_3); // borrow of moved value
252301```
253302
254- ### 键值对容器类型
303+ # 键值对容器类型
255304同时, 该库还支持键值对容器类型, HashMap, BTreeMap
256305并且支持三种键值对分隔符 "=>" ":" ","
257306
@@ -285,7 +334,7 @@ assert_eq!(
285334);
286335```
287336
288- ### 一些细节
337+ # 一些细节
289338vector! : push() 添加元素
290339
291340binary_heap! : push() 添加元素
@@ -302,7 +351,7 @@ b_tree_map! : insert() 添加键值对
302351
303352b_tree_set! : insert() 添加元素
304353
305- ## 迭代器推导式
354+ # 迭代器推导式
306355该库也支持迭代器推导式, 但作为作者我并不推荐使用, 原因如下:
3073561 . 在集合推导式中, 我们也是通过引用进行推导的, 只要我们不消耗原集合, 那么就能做到相同的事情
3083572 . 得到引用的副本的代价并不大
@@ -407,17 +456,40 @@ let mut result3 = {
407456use better_comprehension :: vector;
408457use std :: collections :: {HashMap , BTreeMap };
409458// 创建3x3矩阵
459+
460+ // python-like
410461let matrix = vector! [
411462 vector! [i * 3 + j + 1 for j in 0 .. 3 ]
412463 for i in 0 .. 3
413464];
414465
466+ // 更推荐的写法
467+ let matrix = vector! [
468+ row
469+ for i in 0 .. 3
470+ let row = vector! [
471+ i * 3 + j + 1
472+ for j in 0 .. 3
473+ ]
474+ ];
475+
415476// 矩阵转置
477+ // python-like
416478let transposed = vector! [
417479vector! [row [i ]
418480 for row in matrix . iter ()]
419481for i in 0 .. 3
420482];
483+
484+ // 更推荐的写法
485+ let transposed = vector! [
486+ row
487+ for i in 0 .. 3
488+ let row = vector! [
489+ row [i ]
490+ for row in matrix . iter ()
491+ ]
492+ ];
421493// matrix is alive
422494assert_eq! (matrix , vec! [vec! [1 , 2 , 3 ],
423495 vec! [4 , 5 , 6 ],
@@ -503,29 +575,39 @@ assert_eq!(
503575 (& " Bob" . to_string (), 78 )]));
504576
505577// use for loop
506- let high_scores = {
507- let mut high_scores = BTreeMap :: new ();
578+ let name_high_scores_map = {
579+ let mut name_high_scores_map = BTreeMap :: new ();
508580 for student in & students_data {
509581 let mut subjects = Vec :: new ();
510582 for score in & student . scores {
511583 if score . score >= 85 {
512584 subjects . push (score . subject);
513585 }
514586 }
515- high_scores . insert (& student . name, subjects );
587+ name_high_scores_map . insert (& student . name, subjects );
516588 }
517- high_scores
589+ name_high_scores_map
518590};
519591// ↓ 等价于 ↓
520- // use comprehension!
521- let high_scores = b_tree_map! [
592+ // use comprehension! (python-like)
593+ let name_high_scores_map = b_tree_map! [
522594 & student . name =>
523595 vector! [score . subject for score in & student . scores if score . score >= 85 ]
524596 for student in & students_data
525597];
598+ // ↓ 等价于 ↓
599+ // 更推荐的写法
600+ let name_high_scores_map = b_tree_map! [
601+ & student . name => subjects
602+ for student in & students_data
603+ let subjects = vector! [
604+ score . subject
605+ for score in & student . scores if score . score >= 85
606+ ]
607+ ];
526608
527609assert_eq! (
528- high_scores ,
610+ name_high_scores_map ,
529611 BTreeMap :: from ([
530612 (& " Alice" . to_string (), vec! [" Math" , " English" ]),
531613 (& " Bob" . to_string (), vec! [" English" ])
0 commit comments