1#![doc(html_logo_url = "https://raw.githubusercontent.com/mattgathu/cute/master/C!.png")]
2#[macro_export]
142macro_rules! c {
143
144 ($exp:expr, for $i:ident in $iter:expr) => (
145 {
146 let mut r = vec![];
147 for $i in $iter {
148 r.push($exp);
149 }
150 r
151 }
152 );
153
154 ($exp:expr, for $i:ident in $iter:expr, if $cond:expr) => (
155 {
156 let mut r = vec![];
157 for $i in $iter {
158 if $cond {
159 r.push($exp.clone());
160 }
161 }
162 r
163 }
164 );
165
166 ($exp:expr, for $i:ident in $iter:expr, for $i2:ident in $iter2:expr) => (
167 {
168 let mut r = vec![];
169 for $i2 in $iter2 {
170 for $i in $iter {
171 r.push($exp);
172 }
173 }
174 r
175 }
176 );
177
178 ($exp:expr, for $i:ident in $iter:expr, for $i2:ident in $iter2:expr, if $cond:expr) => (
179 {
180 let mut r = vec![];
181 for $i2 in $iter2 {
182 for $i in $iter {
183 if $cond{
184 r.push($exp);
185 }
186 }
187 }
188 r
189 }
190 );
191
192 ($key:expr => $val:expr, for $p:pat in $iter:expr) => (
193 {
194 use std::collections::HashMap;
195 let mut map = HashMap::new();
196 for $p in $iter {
197 map.insert($key, $val);
198 }
199 map
200 }
201 );
202
203 ($key:expr => $val:expr, for $p:pat in $iter:expr, if $cond:expr) => (
204 {
205 use std::collections::HashMap;
206 let mut map = HashMap::new();
207 for $p in $iter {
208 if $cond {
209 map.insert($key, $val);
210 }
211 }
212 map
213 }
214 );
215
216 ($key:expr => $val:expr, for $i:ident in $iter:expr) => (
217 {
218 use std::collections::HashMap;
219 let mut map = HashMap::new();
220 for $i in $iter {
221 map.insert($key, $val);
222 }
223 map
224 }
225 );
226
227 ($key:expr => $val:expr, for $i:ident in $iter:expr, if $cond:expr) => (
228 {
229 use std::collections::HashMap;
230 let mut map = HashMap::new();
231 for $i in $iter {
232 if $cond {
233 map.insert($key, $val);
234 }
235 }
236 map
237 }
238 );
239}
240
241#[cfg(test)]
242mod tests {
243 use std::collections::HashMap;
244 #[test]
245 fn simple_comprehension() {
246 let squares: Vec<usize> = c![x*x, for x in 0..10];
247 assert_eq!(squares, vec![0, 1, 4, 9, 16, 25, 36, 49, 64, 81]);
248 }
249
250 #[test]
251 fn filter_comprehension() {
252 let squares = c![x*x, for x in 0..10, if x % 2 == 0];
253 assert_eq!(squares, vec![0, 4, 16, 36, 64]);
254 }
255
256 #[test]
257 fn simple_nested_comprehension() {
258 let nested = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
259 let flat: Vec<usize> = c![x, for x in y, for y in nested];
260 assert_eq!(flat, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
261 }
262
263 #[test]
264 fn filter_nested_comprehension() {
265 let nested = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
266 let even_flat: Vec<usize> = c![x, for x in y, for y in nested, if x % 2 == 0];
267 assert_eq!(even_flat, vec![2, 4, 6, 8]);
268 }
269
270
271 #[test]
272 fn vector_to_iter_comprehension() {
273 let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
274 let output: Vec<i32> = c![x*2, for x in vec.iter()];
275 assert_eq!(output, vec![-8, -4, 0, 4, 8]);
276 }
277
278 #[test]
279 fn filter_comprehension_two() {
280 let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
281 let output: Vec<i32> = c![x, for x in vec.iter(), if *x >= 0i32];
282 assert_eq!(output, vec![0, 2, 4]);
283 }
284
285 #[test]
286 fn apply_function_comprehension() {
287 let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
288 let output: Vec<i32> = c![x.abs(), for x in vec.iter()];
289 assert_eq!(output, vec![4, 2, 0, 2, 4]);
290 }
291
292 #[test]
293 fn apply_user_defined_function() {
294 fn square(x: i32) -> i32 {
295 x * x
296 }
297
298 let vec: Vec<i32> = vec![-4, -2, 0, 2, 4];
299 let squares: Vec<i32> = c![square(x), for x in vec];
300 assert_eq!(squares, vec![16, 4, 0, 4, 16]);
301 }
302
303 #[test]
304 fn hashmap_comprehension() {
305 let v = vec!["one", "two", "three"];
306 let map = c! {key => key.to_uppercase(), for key in v};
307 let mut expected: HashMap<&str, String> = HashMap::new();
308 expected.insert("one", String::from("ONE"));
309 expected.insert("two", String::from("TWO"));
310 expected.insert("three", String::from("THREE"));
311
312 assert_eq!(map, expected);
313 }
314
315 #[test]
316 fn hashmap_comprehension_two() {
317 let v = vec!["one", "two", "three"];
318 let map = c! {format!("{}-true", key) => key.to_uppercase(), for key in v};
319 let mut expected: HashMap<String, String> = HashMap::new();
320 expected.insert(String::from("one-true"), String::from("ONE"));
321 expected.insert(String::from("two-true"), String::from("TWO"));
322 expected.insert(String::from("three-true"), String::from("THREE"));
323
324 assert_eq!(map, expected);
325 }
326
327 #[test]
328 fn hashmap_comprehension_three() {
329 let v: Vec<(String, i32)> = vec![(String::from("one"), 1), (String::from("two"), 2), (String::from("three"), 3)];
330 let map = c! {key => val, for (key, val) in v};
331
332 let mut expected: HashMap<String, i32> = HashMap::new();
333 expected.insert(String::from("one"), 1);
334 expected.insert(String::from("two"), 2);
335 expected.insert(String::from("three"), 3);
336
337 assert_eq!(map, expected);
338 }
339
340
341 #[test]
342 fn hashmap_tuple_comprehension() {
343 let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
344 let map = c! {key => val, for (key, val) in v};
345
346 let mut expected: HashMap<&str, i32> = HashMap::new();
347 expected.insert("one", 1);
348 expected.insert("two", 2);
349 expected.insert("three", 3);
350
351 assert_eq!(map, expected);
352 }
353
354 #[test]
355 fn conditional_hashmap_tuple_comprehension() {
356 let v: Vec<(&str, i32)> = vec![("one", 1), ("two", 2), ("three", 3)];
357 let map = c! {key => val, for (key, val) in v, if val == 1 || val == 2};
358
359 let mut expected: HashMap<&str, i32> = HashMap::new();
360 expected.insert("one", 1);
361 expected.insert("two", 2);
362
363 assert_eq!(map, expected);
364 }
365
366 #[test]
367 fn hashmap_from_iter() {
368 let map = c! {*key => key*key, for key in vec![1,2].iter()};
369 let mut e: HashMap<i32, i32> = HashMap::new();
370 e.insert(1, 1);
371 e.insert(2, 4);
372
373 assert_eq!(map, e);
374 }
375
376 #[test]
377 fn conditional_hashmap_from_iter() {
378 let map = c! {*key => key*key, for key in vec![1,2].iter(), if *key % 2 == 0};
379 let mut e: HashMap<i32, i32> = HashMap::new();
380 e.insert(2, 4);
381
382 assert_eq!(map, e);
383 }
384
385 #[test]
386 fn hashmap_from_range() {
387 let map = c! {key => key*key, for key in 1..3};
388 let mut e: HashMap<i32, i32> = HashMap::new();
389 e.insert(1, 1);
390 e.insert(2, 4);
391
392 assert_eq!(map, e);
393 }
394
395 #[test]
396 fn conditional_hashmap_from_range() {
397 let map = c! {key => key*key, for key in 1..6, if key % 2 == 1};
398 let mut e: HashMap<i32, i32> = HashMap::new();
399 e.insert(1, 1);
400 e.insert(3, 9);
401 e.insert(5, 25);
402
403 assert_eq!(map, e);
404 }
405}