Macro collect_array

Source
macro_rules! collect_array {
    ($it:expr; $n:expr) => { ... };
    ($e:expr; $ph:pat in $ih:expr $( , $pt:pat in $it:expr )* $(; where $($cond:expr),+ )? ; $n:expr) => { ... };
    ($( $p:pat in $i:expr ),+ => $e:expr $(; where $($cond:expr),+ )? ; $n:expr) => { ... };
}
Expand description

Constructs arrays by repeating expression with elements from iterators bound to provided patterns.

Creating arrays from iterators is really handy. But it comes at price - there could be not enough values in the iterator to fill the array.

Therefore this macro returns Option. Some array is returned if there were enough values. Otherwise None is returned.

let opt = collect_array![1..; 3];

assert_eq!(opt, Some([1, 2, 3]));

None is returned otherwise.

let opt = collect_array![1..3; 3];

assert_eq!(opt, None, "There's only two elements in 1..3");

Similarly to array! macro, collect_array can be given a pattern to bind iterator elements and expression to produce array elements.

let opt = collect_array![x in 1.. => x / 2; 3];

assert_eq!(opt, Some([0, 1, 1]));

But why stop there? Multiple iterators can be collected into an array!

let opt = collect_array![x in 1.., y in 2.. => x + y; 3];

assert_eq!(opt, Some([3, 5, 7]));

Surely it also supports predicates. When predicate evaluates to false, next items are taken from all iterators.

let opt = collect_array![x in 1.., y in 2.. => x + y; where x * y > 10; 3];

assert_eq!(opt, Some([7, 9, 11]));

Patterns support destructuring.

let values = collect_array![(x, y) in [(1, 2), (3, 4), (5, 6)] => x + y; 3];

assert_eq!(values, Some([3, 7, 11]));

And patterns don’t have to be irrefutable.

let values = collect_array![(1, y) in [(1, 2), (3, 4), (1, 6)] => y; 2];

assert_eq!(values, Some([2, 6]));