Skip to content

Commit 61d1855

Browse files
更新文档与README
1 parent 595aa21 commit 61d1855

File tree

5 files changed

+257
-10
lines changed

5 files changed

+257
-10
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ keywords = [
1212
]
1313
repository = "https://github.com/Natural-selection1/better-comprehension-in-rust"
1414
readme = "README.md"
15-
version = "1.0.1"
15+
version = "1.0.2"
1616
edition = "2024"
1717
exclude = ["src/main.rs", "target", ".vscode", "README-CN.md",".gitignore"]
1818

README-CN.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,13 @@ None
185185
```rust
186186
let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
187187
let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];
188-
189188
let mut result3 = {
190189
let vec_2 = vec_2.iter().collect::<Vec<_>>();
191190
let vec_1 = vec_1.iter().collect::<Vec<_>>();
192191
(vec_1).into_iter().filter_map(move |x| {
193192
(x.contains("1") || x.contains("7")).then(|| {
194193
let vec_2 = vec_2.clone();
195-
(1..=2).into_iter().filter_map(move |i| {
194+
(1..=2).into_iter().filter_map(move |_| {
196195
(true).then(|| {
197196
let vec_2 = vec_2.clone();
198197
(vec_2).into_iter().filter_map(move |y| {
@@ -207,8 +206,9 @@ let mut result3 = {
207206
})
208207
})
209208
})
210-
.flatten()
211-
.flatten()
209+
})
210+
.flatten()
211+
.flatten()
212212
};
213213
```
214214

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,13 @@ The above writing is equivalent to the following writing
185185
```rust
186186
let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
187187
let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];
188-
189188
let mut result3 = {
190189
let vec_2 = vec_2.iter().collect::<Vec<_>>();
191190
let vec_1 = vec_1.iter().collect::<Vec<_>>();
192191
(vec_1).into_iter().filter_map(move |x| {
193192
(x.contains("1") || x.contains("7")).then(|| {
194193
let vec_2 = vec_2.clone();
195-
(1..=2).into_iter().filter_map(move |i| {
194+
(1..=2).into_iter().filter_map(move |_| {
196195
(true).then(|| {
197196
let vec_2 = vec_2.clone();
198197
(vec_2).into_iter().filter_map(move |y| {
@@ -207,8 +206,9 @@ let mut result3 = {
207206
})
208207
})
209208
})
210-
.flatten()
211-
.flatten()
209+
})
210+
.flatten()
211+
.flatten()
212212
};
213213
```
214214

src/lib.rs

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,250 @@
1+
//! # better_comprehension
2+
//! [中文README](https://github.com/Natural-selection1/better-comprehension-in-rust/blob/master/README-CN.md)
3+
//!
4+
//! Collection comprehension and Iterator comprehension in Rust. And it provides a better experience in Rust.
5+
//!
6+
//! # Usage
7+
//!
8+
//! The syntax is derived from [Python's comprehension](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions).
9+
//!
10+
//! This library provides macros for all collection types in the Rust standard library and an Iterator based on references.
11+
//!
12+
//! ---
13+
//! simple example
14+
//! ```rust
15+
//! use better_comprehension::vector;
16+
//! let vec_1 = vec!["AB".to_string(), "CD".to_string()];
17+
//! let vec: Vec<String> = vector![x.clone() for x in vec_1];
18+
//! assert_eq!(vec, vec!["AB".to_string(), "CD".to_string()]);
19+
//! ```
20+
//! ---
21+
//! You can also use patterns in it
22+
//! ```rust
23+
//! use better_comprehension::vec_deque;
24+
//! use std::collections::VecDeque;
25+
//! struct Person {
26+
//! name: String,
27+
//! age: i32,
28+
//! }
29+
//! let people = [Person { name: "Joe".to_string(), age: 20 },
30+
//! Person { name: "Bob".to_string(), age: 25 }];
31+
//! let vec_deque = vec_deque![ name.clone()
32+
//! for Person { name, ..} in people];
33+
//! assert_eq!(vec_deque,
34+
//! VecDeque::from(["Joe".to_string(),
35+
//! "Bob".to_string()]));
36+
//! ```
37+
//! ---
38+
//! filtering values before comprehension
39+
//! ```rust
40+
//! use better_comprehension::linked_list;
41+
//! use std::collections::LinkedList;
42+
//! let linked_list = linked_list![ i*2 for i in 1..=3 if i != 2 ];
43+
//! assert_eq!(linked_list, LinkedList::from([2, 6]));
44+
//! ```
45+
//! ---
46+
//! return different values based on conditions
47+
//! ```rust
48+
//! use better_comprehension::b_tree_set;
49+
//! use std::collections::BTreeSet;
50+
//! let b_tree_set = b_tree_set!{
51+
//! i if i-1 == 0 else i+10
52+
//! for i in 1..=3 if i != 2
53+
//! };
54+
//! assert_eq!(b_tree_set, BTreeSet::from([1, 13]));
55+
//! ```
56+
//! ---
57+
//! nested comprehension
58+
//! ```rust
59+
//! use better_comprehension::binary_heap;
60+
//! use std::collections::BinaryHeap;
61+
//! let binary_heap = binary_heap![
62+
//! i if (i-1 == 0 || j -2 == 0) else i+10
63+
//! for i in 1..=3 if i != 2
64+
//! for j in 1..=3 if j+i != 4];
65+
//! assert_eq!(binary_heap.into_sorted_vec(), vec![1, 1, 3, 13]);
66+
//! ```
67+
//! ---
68+
//! the reading order of the for loop in this library is from top to bottom, just like Python's comprehension.
69+
//! ```rust
70+
//! use better_comprehension::vector;
71+
//! let vec = vector![
72+
//! (top,bottom)
73+
//! for top in 1..=3 if top != 2
74+
//! for bottom in 4..=6 if bottom+top != 4];
75+
//! assert_eq!(vec, vec![(1, 4), (1, 5), (1, 6),
76+
//! (3, 4), (3, 5), (3, 6)]);
77+
//! ```
78+
//! ---
79+
//!
80+
//! Note that in Rust, for loops consume ownership.
81+
//! So typically, for nested loops, if you want the original container to be consumed, you should write it like this:
82+
//!
83+
//! ```rust
84+
//! use better_comprehension::vector;
85+
//! let vec_1 = vec!["ABC".to_string(), "DEF".to_string()];
86+
//! let vec_2 = vec!["abc".to_string(), "def".to_string()];
87+
//! let vec_3 = vec![123, 456];
88+
//! let vec = {
89+
//! // shadow the variable you want to consume
90+
//! let vec_1 = vec_1;
91+
//! let vec_3 = vec_3;
92+
//!
93+
//! let mut vec = vec![];
94+
//! for i in vec_1.iter() {
95+
//! if i == "ABC" {
96+
//! // In the inner loop, you must use iter(),
97+
//! // otherwise ownership will be transferred for the first time
98+
//! for j in vec_2.iter() {
99+
//! if j == "abc" {
100+
//! // If you do not use iter(),
101+
//! // then the ownership of vec_3
102+
//! // will be transferred for the first time
103+
//! for k in vec_3.iter() {
104+
//! if k == &123 {
105+
//! // Only use clone when necessary
106+
//! // to avoid unnecessary resource waste
107+
//! vec.push((i.clone(), j.clone(), *k));
108+
//! }
109+
//! }
110+
//! }
111+
//! }
112+
//! }
113+
//! }
114+
//! vec
115+
//! };
116+
//! // println!("{:?}", vec_1); // borrow of moved value
117+
//! println!("{:?}", vec_2); // work well
118+
//! // println!("{:?}", vec_3); // borrow of moved value
119+
//! ```
120+
//! ---
121+
//! But in this library, you don't need to do this,
122+
//!
123+
//! the provided macros will automatically handle these problems for you.
124+
//!
125+
//! You only need to add .iter() or use & before the variable you want to keep ownership,
126+
//!
127+
//! the rest will be automatically handled in the macro.
128+
//! ```rust
129+
//! use better_comprehension::vector;
130+
//! let vec_1 = vec!["ABC".to_string(), "DEF".to_string()];
131+
//! let vec_2 = vec!["abc".to_string(), "def".to_string()];
132+
//! let vec_3 = vec![123, 456];
133+
//! let vec = vector![
134+
//! (i.clone(),j.clone(),*k)
135+
//! for i in vec_1 if i == "ABC"
136+
//! for j in vec_2.iter() if j == "abc"
137+
//! // for j in &vec_2 if j == "abc" // this is also reasonable
138+
//! for k in vec_3 if k == &123
139+
//! ];
140+
//! // println!("{:?}", vec_1); // borrow of moved value
141+
//! println!("{:?}", vec_2); // work well
142+
//! // println!("{:?}", vec_3); // borrow of moved value
143+
//! ```
144+
//! ---
145+
//! This library also supports key-value collection types, HashMap, BTreeMap
146+
//! ```rust
147+
//! use better_comprehension::hash_map;
148+
//! use std::collections::HashMap;
149+
//! let vec_key = vec!["key_1".to_string(), "key_2".to_string(), "key_3".to_string()];
150+
//! let vec_value = [1, 2, 3];
151+
//! let hash_map = hash_map!{
152+
//! // the following three key-value pair separators are supported
153+
//! key.clone() : *value
154+
//! // key.clone() => *value
155+
//! // key.clone() , *value
156+
//! for key in vec_key
157+
//! for value in vec_value
158+
//! };
159+
//! assert_eq!(
160+
//! hash_map,
161+
//! HashMap::from([
162+
//! ("key_1".to_string(), 3),
163+
//! ("key_2".to_string(), 3),
164+
//! ("key_3".to_string(), 3)
165+
//! ])
166+
//! );
167+
//! ```
168+
//! ---
169+
//! Iterator comprehension is also supported,but unlike the collection comprehension above,
170+
//!
171+
//! this iterator comprehension is based on references,so it will not consume ownership.
172+
//! ```rust
173+
//! use better_comprehension::iterator_ref;
174+
//! let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
175+
//! let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];
176+
177+
//! let mut result3 = iterator_ref![
178+
//! (x.clone(), y.clone()) if x.contains("1") else (y.clone(), x.clone())
179+
//! for x in vec_1 if x.contains("1") || x.contains("7")
180+
//! for i in 1..=2
181+
//! for y in vec_2 if y.contains("D") || x.contains("3")];
182+
183+
//! for _ in 0..=9 {
184+
//! println!("{:?}", result3.next());
185+
//! }
186+
//! /*
187+
//! Some(("123", "ABC"))
188+
//! Some(("123", "DEF"))
189+
//! Some(("123", "GHI"))
190+
//! Some(("123", "ABC"))
191+
//! Some(("123", "DEF"))
192+
//! Some(("123", "GHI"))
193+
//! Some(("789", "DEF"))
194+
//! Some(("789", "DEF"))
195+
//! None
196+
//! None
197+
//! */
198+
//! ```
199+
200+
//! The above writing is equivalent to the following writing
201+
//!```rust
202+
//!let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
203+
//!let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];
204+
//!let mut result3 = {
205+
//! let vec_2 = vec_2.iter().collect::<Vec<_>>();
206+
//! let vec_1 = vec_1.iter().collect::<Vec<_>>();
207+
//! (vec_1).into_iter().filter_map(move |x| {
208+
//! (x.contains("1") || x.contains("7")).then(|| {
209+
//! let vec_2 = vec_2.clone();
210+
//! (1..=2).into_iter().filter_map(move |_| {
211+
//! (true).then(|| {
212+
//! let vec_2 = vec_2.clone();
213+
//! (vec_2).into_iter().filter_map(move |y| {
214+
//! (y.contains("D") || x.contains("3")).then(|| {
215+
//! if x.contains("1") {
216+
//! (x.clone(), y.clone())
217+
//! } else {
218+
//! (y.clone(), x.clone())
219+
//! }
220+
//! })
221+
//! })
222+
//! })
223+
//! })
224+
//! })
225+
//! })
226+
//! .flatten()
227+
//! .flatten()
228+
//!};
229+
//!```
230+
//! # some details
231+
//!
232+
//! vector! : push() to add elements
233+
//!
234+
//! vec_deque! : push_back() to add elements
235+
//!
236+
//! linked_list! : push_back() to add elements
237+
//!
238+
//! binary_heap! : push() to add elements
239+
//!
240+
//! hash_set! : insert() to add elements
241+
//!
242+
//! b_tree_set! : insert() to add elements
243+
//!
244+
//! hash_map! : insert() to add key-value pairs
245+
//!
246+
//! b_tree_map! : insert() to add key-value pairs
247+
1248
use proc_macro::TokenStream as TS;
2249

3250
mod eager_evaluation;

0 commit comments

Comments
 (0)