@@ -8,53 +8,56 @@ This library aims to be a good alternative to all comprehension libraries,
8
8
for the libraries you encounter when searching "comprehension" on crate.io,
9
9
we have already done:
10
10
Fully covered libraries:
11
- * [ comprehension] ( https://crates.io/crates/comprehension )
12
- * [ kt-list-comprehensions] ( https://crates.io/crates/kt-list-comprehensions )
13
- * [ iter-comprehensions] ( https://crates.io/crates/iter-comprehensions )
14
- * [ cute] ( https://crates.io/crates/cute )
11
+ * [ comprehension] ( https://crates.io/crates/comprehension )
12
+ * [ kt-list-comprehensions] ( https://crates.io/crates/kt-list-comprehensions )
13
+ * [ iter-comprehensions] ( https://crates.io/crates/iter-comprehensions )
14
+ * [ cute] ( https://crates.io/crates/cute )
15
15
16
16
Partially covered libraries:
17
17
* [ list_comprehension_macro] ( https://crates.io/crates/list_comprehension_macro )
18
- * Does not provide a unified macro that distinguishes by mapping expression (like real Python comprehensions)
18
+ * Does not provide a unified macro that distinguishes by mapping expression (like real Python comprehensions)
19
+
19
20
(No plans to support this, as this library already provides all collection types in the Rust standard library)
20
21
21
- * Does not support while loop
22
+ * Does not support while loop
22
23
23
24
* [ list_comprehension] ( https://crates.io/crates/list_comprehension )
24
- * Does not support let-else variable binding
25
- (No plans to support this, as it overly complicates the for-in part, and these things can be completely solved in the mapping return block)
25
+ * Does not support let-else variable binding
26
26
27
- # Usage
27
+ (No plans to support this, as it overly complicates the for-in part, and these things can be completely solved in the mapping return block)
28
28
29
- ## Collection Comprehensions
29
+ # Collection Comprehensions
30
30
31
31
You can completely treat collection comprehension macros as sugar for ` for loop `
32
32
(In fact, these macros are implemented using ` for loop ` )
33
33
So you'll see many familiar syntaxes
34
34
However, they will be more ergonomic and easier to read and use
35
35
36
- ### Simple Example
36
+ # Simple Example
37
37
``` rust
38
38
use better_comprehension :: vector;
39
39
let vec_1 = vec! [" AB" . to_string (), " CD" . to_string ()];
40
40
let vec_2 = vec! [" 12" . to_string (), " 34" . to_string ()];
41
41
42
42
43
- // Ownership consuming iteration (just pass the single identifier)
43
+ // Ownership consuming iteration
44
+ // (just pass the single identifier)
44
45
// x's type is &String
45
46
let vec : Vec <String > = vector! [x . clone () for x in vec_1 ];
46
47
// println!("{:?}", vec_1); // borrow of moved value
47
48
assert_eq! (vec , vec! [" AB" . to_string (), " CD" . to_string ()]);
48
49
49
- // Ownership preserving iteration (pass &collection or collection.iter().other_method())
50
+ // Ownership preserving iteration
51
+ // (pass &collection or collection.iter().other_method())
50
52
// x's type is &String
51
53
let vec : Vec <String > = vector! [x . clone () for x in vec_2 . iter ()];
52
- // let vec: Vec<String> = vector![x.clone() for x in &vec_2]; // equivalent writing
54
+ // equivalent writing
55
+ // let vec: Vec<String> = vector![x.clone() for x in &vec_2];
53
56
println! (" {:?}" , vec_2 ); // vec_2 is alive
54
57
assert_eq! (vec , vec! [" 12" . to_string (), " 34" . to_string ()]);
55
58
```
56
59
57
- ### if in collection
60
+ # if in comprehension
58
61
59
62
` for ` pattern ` in ` collection ` if ` ... will be translated to
60
63
``` rust
@@ -65,14 +68,17 @@ for pattern in collection {
65
68
}
66
69
```
67
70
68
- #### if conditions as filtering conditions
71
+ ## if conditions as filtering conditions
69
72
Where conditions is any expression that returns a bool
70
73
Only when the expression returns true, it will be mapped
71
74
``` rust
72
75
use better_comprehension :: linked_list;
73
76
use std :: collections :: LinkedList ;
74
77
// i's type is i32
75
- let linked_list = linked_list! [ i * 2 for i in 1 ..= 3 if i != 2 ];
78
+ let linked_list = linked_list! [
79
+ i * 2
80
+ for i in 1 ..= 3 if i != 2
81
+ ];
76
82
assert_eq! (linked_list , LinkedList :: from ([2 , 6 ]));
77
83
```
78
84
@@ -81,22 +87,29 @@ use better_comprehension::linked_list;
81
87
use std :: collections :: LinkedList ;
82
88
let judge_function = | i : i32 | i != 2 ;
83
89
// i's type is i32
84
- let linked_list = linked_list! [ i * 2 for i in 1 ..= 3 if judge_function (i ) ];
90
+ let linked_list = linked_list! [
91
+ i * 2
92
+ for i in 1 ..= 3 if judge_function (i )
93
+ ];
85
94
assert_eq! (linked_list , LinkedList :: from ([2 , 6 ]));
86
95
```
87
96
88
- #### if let expression
97
+ ## if let expression
89
98
``` rust
90
99
use better_comprehension :: vector;
91
- let vec_1 = vec! [Some (" 123" . to_string ()), None , Some (" 456" . to_string ())];
100
+ let vec_1 = vec! [Some (" 123" . to_string ()),
101
+ None ,
102
+ Some (" 456" . to_string ())];
92
103
let vec = vector! [
93
104
__x__ . clone ()
94
105
for x in vec_1 if let Some (__x__ ) = x
95
106
];
96
- assert_eq! (vec , vec! [" 123" . to_string (), " 456" . to_string ()]);
107
+ assert_eq! (vec , vec! [" 123" . to_string (),
108
+ " 456" . to_string ()]
109
+ );
97
110
```
98
111
99
- #### Return different values based on conditions
112
+ # Return different values based on conditions
100
113
``` rust
101
114
use better_comprehension :: b_tree_set;
102
115
use std :: collections :: BTreeSet ;
@@ -107,7 +120,7 @@ let b_tree_set = b_tree_set!{
107
120
assert_eq! (b_tree_set , BTreeSet :: from ([1 , 13 ]));
108
121
```
109
122
110
- ### Use pattern matching
123
+ # Use pattern matching
111
124
``` rust
112
125
use better_comprehension :: vec_deque;
113
126
use std :: collections :: VecDeque ;
@@ -118,7 +131,7 @@ struct Person {
118
131
}
119
132
120
133
let people = [Person { name : " Joe" . to_string (), age : 20 },
121
- Person { name : " Bob" . to_string (), age : 25 }];
134
+ Person { name : " Bob" . to_string (), age : 25 }];
122
135
123
136
// name's type is &String
124
137
let vec_deque : VecDeque <String > = vec_deque! [
@@ -130,7 +143,7 @@ println!("{:?}", people); // people is alive
130
143
assert_eq! (vec_deque , VecDeque :: from ([" Bob" . to_string ()]));
131
144
```
132
145
133
- ### Nested Comprehensions
146
+ # Nested Comprehensions
134
147
Like Python's comprehensions, this library's for loop is read from top to bottom.
135
148
136
149
``` rust
@@ -151,10 +164,10 @@ let vec = vector![
151
164
for top in 1 ..= 3 if top != 2
152
165
for bottom in 4 ..= 6 if bottom + top != 4 ];
153
166
assert_eq! (vec , vec! [(1 , 4 ), (1 , 5 ), (1 , 6 ),
154
- (3 , 4 ), (3 , 5 ), (3 , 6 )]);
167
+ (3 , 4 ), (3 , 5 ), (3 , 6 )]);
155
168
```
156
169
157
- ### Execute code in block before returning
170
+ # Execute code in block before returning
158
171
This is a very powerful feature, you can execute any code before returning but it will reduce readability, please use it with caution
159
172
``` rust
160
173
use better_comprehension :: vector;
@@ -185,7 +198,7 @@ assert_eq!(
185
198
);
186
199
```
187
200
188
- ### description of ergonomic
201
+ # description of ergonomic
189
202
Please note, in Rust, for loop consumes ownership.
190
203
So usually, for multi-layer loops, if you want the original collection to be consumed, you should write it like this:
191
204
``` rust
@@ -228,6 +241,7 @@ In this library, you don't need to do this, the macros will automatically handle
228
241
You only need to do two things:
229
242
1 . For the collection you want to keep ownership, add ` .iter() ` or use ` & `
230
243
2 . Directly pass the variable name of the collection you want to consume
244
+
231
245
The rest will be automatically handled in the macro.
232
246
``` rust
233
247
use better_comprehension :: vector;
@@ -246,7 +260,7 @@ println!("{:?}", vec_2); // work well
246
260
// println!("{:?}", vec_3); // borrow of moved value
247
261
```
248
262
249
- ### Key-value collection types
263
+ # Key-value collection types
250
264
Also, this library supports key-value collection types, HashMap, BTreeMap
251
265
And supports three key-value separators "=>" ":" ","
252
266
@@ -280,7 +294,7 @@ assert_eq!(
280
294
);
281
295
```
282
296
283
- ### Some details
297
+ # Some details
284
298
vector! : push() to add elements
285
299
286
300
binary_heap! : push() to add elements
@@ -297,7 +311,7 @@ b_tree_map! : insert() to add key-value pairs
297
311
298
312
b_tree_set! : insert() to add elements
299
313
300
- ## Iterator Comprehensions
314
+ # Iterator Comprehensions
301
315
This library also supports iterator comprehensions, but as the author, I do not recommend using them, the reasons are as follows:
302
316
1 . In the collection comprehension, we also use references to derive, as long as we do not consume the original collection, we can achieve the same thing
303
317
2 . The cost of getting a reference copy is not large
@@ -311,11 +325,11 @@ However, to ensure the correctness of the iterator comprehension, only two itera
311
325
``` rust
312
326
use better_comprehension :: iterator_ref;
313
327
let vec_1 = [" 123" . to_string (),
314
- " 456" . to_string (),
315
- " 789" . to_string ()];
328
+ " 456" . to_string (),
329
+ " 789" . to_string ()];
316
330
let vec_2 = [" ABC" . to_string (),
317
- " DEF" . to_string (),
318
- " GHI" . to_string ()];
331
+ " DEF" . to_string (),
332
+ " GHI" . to_string ()];
319
333
320
334
let mut result3 = iterator_ref! [
321
335
(x . clone (), y . clone ()) if x . contains (" 1" ) else (y . clone (), x . clone ())
@@ -347,11 +361,11 @@ None
347
361
The above writing is equivalent to the following writing
348
362
``` rust
349
363
let vec_1 = [" 123" . to_string (),
350
- " 456" . to_string (),
351
- " 789" . to_string ()];
364
+ " 456" . to_string (),
365
+ " 789" . to_string ()];
352
366
let vec_2 = [" ABC" . to_string (),
353
- " DEF" . to_string (),
354
- " GHI" . to_string ()];
367
+ " DEF" . to_string (),
368
+ " GHI" . to_string ()];
355
369
356
370
let mut result3 = {
357
371
let vec_2 = vec_2 . iter (). collect :: <Vec <_ >>();
@@ -385,14 +399,14 @@ This implementation makes the following features in collection comprehension una
385
399
386
400
# Differences
387
401
* Ownership consumption:
388
- * Collection comprehension:
402
+ * Collection comprehension:
389
403
* Using & or .iter() does not consume ownership
390
404
* Directly passing the variable name consumes ownership
391
- * Iterator comprehension:
405
+ * Iterator comprehension:
392
406
* Always does not consume ownership, but only allows passing in a single identifier and range expression that does not follow any method calls
393
407
394
408
* Differences in features:
395
- * if let expression
409
+ * if let expression
396
410
* Collection comprehension: supported
397
411
* Iterator comprehension: not supported
398
412
@@ -420,8 +434,8 @@ assert_eq!(matrix, vec![vec![1, 2, 3],
420
434
assert_eq! (
421
435
transposed ,
422
436
vec! [vec! [1 , 4 , 7 ],
423
- vec! [2 , 5 , 8 ],
424
- vec! [3 , 6 , 9 ]]
437
+ vec! [2 , 5 , 8 ],
438
+ vec! [3 , 6 , 9 ]]
425
439
);
426
440
```
427
441
@@ -495,7 +509,7 @@ let math_scores: HashMap<&String, u8> = hash_map![
495
509
assert_eq! (
496
510
math_scores ,
497
511
HashMap :: from ([(& " Alice" . to_string (), 95 ),
498
- (& " Bob" . to_string (), 78 )]));
512
+ (& " Bob" . to_string (), 78 )]));
499
513
500
514
// use for loop
501
515
let high_scores = {
0 commit comments