better_comprehension 1.0.2

collection and iterator comprehensions for Rust
Documentation
# better_comprehension

[中文README](https://github.com/Natural-selection1/better-comprehension-in-rust/blob/master/README-CN.md)

Collection comprehension and Iterator comprehension in Rust. And it provides a better experience in Rust.

# Usage

The syntax is derived from [Python's comprehension](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions).

This library provides macros for all collection types in the Rust standard library and an Iterator based on references.

---
simple example
```rust
let vec_1 = vec!["AB".to_string(), "CD".to_string()];
let vec: Vec<String> = vector![x.clone() for x in vec_1];
assert_eq!(vec, vec!["AB".to_string(), "CD".to_string()]);
```

---
You can also use patterns in it
```rust
struct Person {
    name: String,
    age: i32,
}
let people = [Person { name: "Joe".to_string(), age: 20 },
              Person { name: "Bob".to_string(), age: 25 }];
let vec_deque = vec_deque![name.clone() for Person { name, .. } in people];
assert_eq!(vec_deque, VecDeque::from(["Joe".to_string(), "Bob".to_string()]));
```
---
filtering values before comprehension
```rust
let linked_list = linked_list![ i*2 for i in 1..=3 if i != 2 ];
assert_eq!(linked_list, LinkedList::from([2, 6]));
```
---
return different values based on conditions
```rust
let b_tree_set = b_tree_set!{
    i if i-1 == 0 else i+10
    for i in 1..=3 if i != 2
    };
assert_eq!(b_tree_set, BTreeSet::from([1, 13]));
```
---
nested comprehension
```rust
let binary_heap = binary_heap![
    i if (i-1 == 0 || j -2 == 0) else i+10
    for i in 1..=3 if i != 2
    for j in 1..=3 if j+i != 4];
assert_eq!(binary_heap.into_sorted_vec(), vec![1, 1, 3, 13]);
```
---
the reading order of the for loop in this library is from top to bottom, just like Python's comprehension.
```rust
let vec = vector![
    (top,bottom)
    for top in 1..=3 if top != 2
    for bottom in 4..=6 if bottom+top != 4];
assert_eq!(vec, vec![(1, 4), (1, 5), (1, 6), (3, 4), (3, 5), (3, 6)]);
```
---

Note that in Rust, for loops consume ownership.
So typically, for nested loops, if you want the original container to be consumed, you should write it like this:

```rust
let vec_1 = vec!["ABC".to_string(), "DEF".to_string()];
let vec_2 = vec!["abc".to_string(), "def".to_string()];
let vec_3 = vec![123, 456];
let vec = {
    // shadow the variable you want to consume
    let vec_1 = vec_1;
    let vec_3 = vec_3;

    let mut vec = vec![];
    for i in vec_1.iter() {
        if i == "ABC" {
            // In the inner loop, you must use iter(),
            // otherwise ownership will be transferred for the first time
            for j in vec_2.iter() {
                if j == "abc" {
                    // If you do not use iter(),
                    // then the ownership of vec_3
                    // will be transferred for the first time
                    for k in vec_3.iter() {
                        if k == &123 {
                            // Only use clone when necessary
                            // to avoid unnecessary resource waste
                            vec.push((i.clone(), j.clone(), *k));
                        }
                    }
                }
            }
        }
    }
    vec
};
// println!("{:?}", vec_1); // borrow of moved value
println!("{:?}", vec_2); // work well
// println!("{:?}", vec_3); // borrow of moved value
```
---
But in this library, you don't need to do this,

the provided macros will automatically handle these problems for you.

You only need to add .iter() or use & before the variable you want to keep ownership,

the rest will be automatically handled in the macro.
```rust
let vec_1 = vec!["ABC".to_string(), "DEF".to_string()];
let vec_2 = vec!["abc".to_string(), "def".to_string()];
let vec_3 = vec![123, 456];
let vec = vector![
    (i.clone(),j.clone(),*k)
    for i in vec_1 if i == "ABC"
    for j in vec_2.iter() if j == "abc"
    // for j in &vec_2 if j == "abc"  // this is also reasonable
    for k in vec_3 if k == &123
];
// println!("{:?}", vec_1); // borrow of moved value
println!("{:?}", vec_2); // work well
// println!("{:?}", vec_3); // borrow of moved value
```
---
This library also supports key-value collection types, HashMap, BTreeMap
```rust
let vec_key = vec!["key_1".to_string(), "key_2".to_string(), "key_3".to_string()];
    let vec_value = [1, 2, 3];
    let hash_map = hash_map!{
        // the following three key-value pair separators are supported
        key.clone() : *value
        // key.clone() => *value
        // key.clone() , *value
        for key in vec_key
        for value in vec_value
    };
    assert_eq!(
        hash_map,
        HashMap::from([
        ("key_1".to_string(), 3),
        ("key_2".to_string(), 3),
        ("key_3".to_string(), 3)
        ])
    );
```
---
Iterator comprehension is also supported,but unlike the collection comprehension above,

this iterator comprehension is based on references,so it will not consume ownership.
```rust
let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];

let mut result3 = iterator_ref![
(x.clone(), y.clone()) if x.contains("1") else (y.clone(), x.clone())
for x in vec_1 if x.contains("1") || x.contains("7")
for i in 1..=2
for y in vec_2 if y.contains("D") || x.contains("3")];

for _ in 0..=9 {
    println!("{:?}", result3.next());
}
/*
Some(("123", "ABC"))
Some(("123", "DEF"))
Some(("123", "GHI"))
Some(("123", "ABC"))
Some(("123", "DEF"))
Some(("123", "GHI"))
Some(("789", "DEF"))
Some(("789", "DEF"))
None
None
*/
```


The above writing is equivalent to the following writing
```rust
let vec_1 = ["123".to_string(), "456".to_string(), "789".to_string()];
let vec_2 = ["ABC".to_string(), "DEF".to_string(), "GHI".to_string()];
let mut result3 = {
    let vec_2 = vec_2.iter().collect::<Vec<_>>();
    let vec_1 = vec_1.iter().collect::<Vec<_>>();
    (vec_1).into_iter().filter_map(move |x| {
        (x.contains("1") || x.contains("7")).then(|| {
            let vec_2 = vec_2.clone();
            (1..=2).into_iter().filter_map(move |_| {
                (true).then(|| {
                    let vec_2 = vec_2.clone();
                    (vec_2).into_iter().filter_map(move |y| {
                        (y.contains("D") || x.contains("3")).then(|| {
                            if x.contains("1") {
                                (x.clone(), y.clone())
                            } else {
                                (y.clone(), x.clone())
                            }
                        })
                    })
                })
            })
        })
    })
    .flatten()
    .flatten()
};
```


# some details

vector! : push() to add elements

vec_deque! : push_back() to add elements

linked_list! : push_back() to add elements

binary_heap! : push() to add elements

hash_set! : insert() to add elements

b_tree_set! : insert() to add elements

hash_map! : insert() to add key-value pairs

b_tree_map! : insert() to add key-value pairs