1#![cfg_attr(
49 feature = "coroutines",
50 feature(coroutines, coroutine_trait, stmt_expr_attributes)
51)]
52
53#[cfg(feature = "coroutines")]
54#[doc(hidden)]
55pub mod iterator_comprehension {
56 #[doc(hidden)]
59 pub struct CoroutineIterator<C: ::std::ops::Coroutine + ::std::marker::Unpin> {
60 coroutine: C,
61 }
62
63 impl<C: ::std::ops::Coroutine + ::std::marker::Unpin> CoroutineIterator<C> {
64 pub fn new(coroutine: C) -> CoroutineIterator<C> {
65 CoroutineIterator { coroutine }
66 }
67 }
68
69 impl<C: ::std::ops::Coroutine + ::std::marker::Unpin> Iterator for CoroutineIterator<C> {
70 type Item = C::Yield;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 use ::std::ops::CoroutineState;
74 match ::std::pin::Pin::new(&mut self.coroutine).resume(()) {
75 CoroutineState::Yielded(y) => Some(y),
76 _ => None,
77 }
78 }
79 }
80
81 #[cfg_attr(
90 feature = "coroutines",
91 doc = r##"
92```rust
93#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
94#[macro_use]
95extern crate mapcomp;
96
97# fn main() {
98let numbers = [8, 3, 5, 7];
99
100let mut powers_of_two = iterc!(1 << x; for x in &numbers);
101
102assert_eq!(Some(256), powers_of_two.next());
103assert_eq!(Some(8), powers_of_two.next());
104assert_eq!(Some(32), powers_of_two.next());
105assert_eq!(Some(128), powers_of_two.next());
106assert_eq!(None, powers_of_two.next());
107# }
108```
109
110Since it only creates an iterator and not a fully populated container, the
111comprehension can be created over an unbounded or infinite iterator.
112
113```rust
114# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
115# #[macro_use] extern crate mapcomp;
116# fn main() {
117let mut odd_squares = iterc!(x * x; for x in 1..; if x % 2 == 1);
118
119assert_eq!(Some(1), odd_squares.next());
120assert_eq!(Some(9), odd_squares.next());
121assert_eq!(Some(25), odd_squares.next());
122assert_eq!(Some(49), odd_squares.next());
123# }
124```
125"##
126 )]
127 #[macro_export]
128 macro_rules! iterc {
129 (@__ $exp:expr; for $item:pat in $iter:expr; if $cond:expr) => (
130 for $item in $iter {
131 if $cond {
132 yield $exp;
133 }
134 }
135 );
136
137 (@__ $exp:expr; for $item:pat in $iter:expr) => (
138 for $item in $iter {
139 yield $exp;
140 }
141 );
142
143 (@__ $exp:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
144 for $item in $iter {
145 if $cond {
146 iterc!(@__ $exp; $($tail)+)
147 }
148 }
149 );
150
151 (@__ $exp:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
152 for $item in $iter {
153 iterc!(@__ $exp; $($tail)+)
154 }
155 );
156
157 ($exp:expr; $($tail:tt)+) => ({
158 let mut coroutine = #[coroutine] || {
159 iterc!(@__ $exp; $($tail)+)
160 };
161 ::mapcomp::iterator_comprehension::CoroutineIterator::new(coroutine)
162 });
163 }
164}
165
166#[macro_export]
191macro_rules! vecc {
192 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr) => (
193 for $item in $iter {
194 if $cond {
195 $acc.push($exp);
196 }
197 }
198 );
199
200 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr) => (
201 for $item in $iter {
202 $acc.push($exp);
203 }
204 );
205
206 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
207 for $item in $iter {
208 if $cond {
209 vecc![@__ $acc, $exp; $($tail)+];
210 }
211 }
212 );
213
214 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
215 for $item in $iter {
216 vecc![@__ $acc, $exp; $($tail)+];
217 }
218 );
219
220 ($exp:expr; $($tail:tt)+) => ({
221 let mut ret = ::std::vec::Vec::new();
222 vecc![@__ ret, $exp; $($tail)+];
223 ret
224 });
225}
226
227#[macro_export]
255macro_rules! hashsetc {
256 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr) => (
257 for $item in $iter {
258 if $cond {
259 $acc.insert($exp);
260 }
261 }
262 );
263
264 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr) => (
265 for $item in $iter {
266 $acc.insert($exp);
267 }
268 );
269
270 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
271 for $item in $iter {
272 if $cond {
273 hashsetc!{@__ $acc, $exp; $($tail)+};
274 }
275 }
276 );
277
278 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
279 for $item in $iter {
280 hashsetc!{@__ $acc, $exp; $($tail)+};
281 }
282 );
283
284 ($exp:expr; $($tail:tt)+) => ({
285 let mut ret = ::std::collections::HashSet::new();
286 hashsetc!{@__ ret, $exp; $($tail)+};
287 ret
288 });
289}
290
291#[macro_export]
320macro_rules! hashmapc {
321 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; if $cond:expr) => (
322 for $item in $iter {
323 if $cond {
324 $acc.insert($key, $val);
325 }
326 }
327 );
328
329 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr) => (
330 for $item in $iter {
331 $acc.insert($key, $val);
332 }
333 );
334
335 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
336 for $item in $iter {
337 if $cond {
338 hashmapc!{@__ $acc, $key => $val; $($tail)+};
339 }
340 }
341 );
342
343 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
344 for $item in $iter {
345 hashmapc!{@__ $acc, $key => $val; $($tail)+};
346 }
347 );
348
349 ($key:expr => $val:expr; $($tail:tt)+) => ({
350 let mut ret = ::std::collections::HashMap::new();
351 hashmapc!{@__ ret, $key => $val; $($tail)+};
352 ret
353 });
354}
355
356#[macro_export]
375macro_rules! btreesetc {
376 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr) => (
377 for $item in $iter {
378 if $cond {
379 $acc.insert($exp);
380 }
381 }
382 );
383
384 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr) => (
385 for $item in $iter {
386 $acc.insert($exp);
387 }
388 );
389
390 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
391 for $item in $iter {
392 if $cond {
393 btreesetc!{@__ $acc, $exp; $($tail)+};
394 }
395 }
396 );
397
398 (@__ $acc:ident, $exp:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
399 for $item in $iter {
400 btreesetc!{@__ $acc, $exp; $($tail)+};
401 }
402 );
403
404 ($exp:expr; $($tail:tt)+) => ({
405 let mut ret = ::std::collections::BTreeSet::new();
406 btreesetc!{@__ ret, $exp; $($tail)+};
407 ret
408 });
409}
410
411#[macro_export]
429macro_rules! btreemapc {
430 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; if $cond:expr) => (
431 for $item in $iter {
432 if $cond {
433 $acc.insert($key, $val);
434 }
435 }
436 );
437
438 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr) => (
439 for $item in $iter {
440 $acc.insert($key, $val);
441 }
442 );
443
444 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; if $cond:expr; $($tail:tt)+) => (
445 for $item in $iter {
446 if $cond {
447 btreemapc!{@__ $acc, $key => $val; $($tail)+};
448 }
449 }
450 );
451
452 (@__ $acc:ident, $key:expr => $val:expr; for $item:pat in $iter:expr; $($tail:tt)+) => (
453 for $item in $iter {
454 btreemapc!{@__ $acc, $key => $val; $($tail)+};
455 }
456 );
457
458 ($key:expr => $val:expr; $($tail:tt)+) => ({
459 let mut ret = ::std::collections::BTreeMap::new();
460 btreemapc!{@__ ret, $key => $val; $($tail)+};
461 ret
462 });
463}
464
465#[cfg(test)]
466mod tests {
467 #[test]
468 fn it_works() {
469 let _v = vecc![x * x; for x in 1..10; if x % 2 == 0];
470 }
471}