Skip to content

Commit

Permalink
added conditional hashmap comprehensions
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgathu committed Jul 17, 2017
1 parent d3a96b2 commit 264bbb1
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
[package]
name = "cute"
version = "0.2.1"
version = "0.3.0"
authors = ["Matt Gathu <[email protected]>"]

description = "A macro for Python-esque comprehensions"
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 115,29 @@ let map = c!{*key => key*key, for key in vec![1,2].iter()};

```

```rust
// conditional hashmap comprehension

let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
let map = c! {key => val, for (key, val) in v, if val == 1 || val == 2};

let mut expected: HashMap<&str, i32> = HashMap::new();
expected.insert("one", 1);
expected.insert("two", 2);

assert_eq!(map, expected);
```

```rust
// conditional hashmap comprehension from an Iterator
// NOTE: we perform deferencing when using values

let map = c! {*key => key*key, for key in vec![1,2].iter(), if *key % 2 == 0};
let mut e: HashMap<i32, i32> = HashMap::new();
e.insert(2, 4);

assert_eq!(map, e);
```



81 changes: 80 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 115,27 @@
//!
//! assert_eq!(map, expected);
//! ```
//!
//! ```
//! // conditional hashmap comprehension
//! let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
//! let map = c! {key => val, for (key, val) in v, if val == 1 || val == 2};
//!
//! let mut expected: HashMap<&str, i32> = HashMap::new();
//! expected.insert("one", 1);
//! expected.insert("two", 2);
//!
//! assert_eq!(map, expected);
//! ```
//!
//! ```
//! // conditional hashmap comprehension from an Iterator
//! let map = c! {*key => key*key, for key in vec![1,2].iter(), if *key % 2 == 0};
//! let mut e: HashMap<i32, i32> = HashMap::new();
//! e.insert(2, 4);
//!
//! assert_eq!(map, e);
//! ```

#[macro_export]
Expand Down Expand Up @@ -179,6 200,19 @@ macro_rules! c {
}
);

($key:expr => $val:expr, for $p:pat in $iter:expr, if $cond:expr) => (
{
use std::collections::HashMap;
let mut map = HashMap::new();
for $p in $iter {
if $cond {
map.insert($key, $val);
}
}
map
}
);

($key:expr => $val:expr, for $i:ident in $iter:expr) => (
{
use std::collections::HashMap;
Expand All @@ -189,6 223,19 @@ macro_rules! c {
map
}
);

($key:expr => $val:expr, for $i:ident in $iter:expr, if $cond:expr) => (
{
use std::collections::HashMap;
let mut map = HashMap::new();
for $i in $iter {
if $cond {
map.insert($key, $val);
}
}
map
}
);
}

#[cfg(test)]
Expand Down Expand Up @@ -292,7 339,7 @@ mod tests {


#[test]
fn hashmap_comprehension_four() {
fn hashmap_tuple_comprehension() {
let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
let map = c! {key => val, for (key, val) in v};

Expand All @@ -304,6 351,18 @@ mod tests {
assert_eq!(map, expected);
}

#[test]
fn conditional_hashmap_tuple_comprehension() {
let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
let map = c! {key => val, for (key, val) in v, if val == 1 || val == 2};

let mut expected: HashMap<&str, i32> = HashMap::new();
expected.insert("one", 1);
expected.insert("two", 2);

assert_eq!(map, expected);
}

#[test]
fn hashmap_from_iter() {
let map = c! {*key => key*key, for key in vec![1,2].iter()};
Expand All @@ -314,6 373,15 @@ mod tests {
assert_eq!(map, e);
}

#[test]
fn conditional_hashmap_from_iter() {
let map = c! {*key => key*key, for key in vec![1,2].iter(), if *key % 2 == 0};
let mut e: HashMap<i32, i32> = HashMap::new();
e.insert(2, 4);

assert_eq!(map, e);
}

#[test]
fn hashmap_from_range() {
let map = c! {key => key*key, for key in 1..3};
Expand All @@ -323,4 391,15 @@ mod tests {

assert_eq!(map, e);
}

#[test]
fn conditional_hashmap_from_range() {
let map = c! {key => key*key, for key in 1..6, if key % 2 == 1};
let mut e: HashMap<i32, i32> = HashMap::new();
e.insert(1, 1);
e.insert(3, 9);
e.insert(5, 25);

assert_eq!(map, e);
}
}

0 comments on commit 264bbb1

Please sign in to comment.