macro_rules! array {
    ($($e:expr),* $(,)?) => { ... };
    ($e:expr; $n:expr) => { ... };
    ($p:pat => $e:expr $( ; where $( $cond:expr ),+ )? ; $n:expr) => { ... };
}
Expand description

Constructs arrays by repeating expression execution, possibly with enumeration bound to provided pattern.

Syntax

On the basic level, arrays construction happens by repeating execution of provided expression multiple times. Note that the expression itself appears exactly once in expanded code. And length expression is executed in const context exactly once.

let values = array![1; 2];

assert_eq!(values, [1, 1]);

Unlike built-in syntax [$expr; $size] array! runs expression $size times instead of copying result. This means that expression will exhibit its side effects for each array element, and value can change freely.

let values: [f32; 2] = array![random(); 2];

This also means that expression type may not be Copy or event Clone.

let values = array![Mutex::new(1); 2];

Enumerate

array! macro supports enumerating while constructing array elements.

array!($pat => $expr ; $n) does the trick. That’s it, simply add $pat => before element expression.

$pat must be valid pattern. And it will be bound to numbers starting from 0. Bound value can be used in the element expression.

let values = array![x => x + 1; 3];

assert_eq!(values, [1, 2, 3]);

Predicates

array! macro supports predicated that are evaluated before element expression for each constructed element. When predicate does not pass, element expression is not executed. Value bound to pattern will be updated before trying again.

let values = array![x => x + 1; where x & 1 == 1; 3];

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

It is possible to make array expression infeasible. For example by providing predicate that never evaluates to true.


// predicate always evaluates to `false`
// making it impossible to construct array of size 1 or greater.
// This will lead to a panic with descriptive message.
// `[u8; 1]` type forces enumerator to be `u8` allowing it to fail faster.
let _: [u8; 1] = array![x => x; where false; 1];

Control flow

Element expressions and conditions are executed in the inner loop scope but in the outer function. This makes it possible to perform early return from macro invocation using return and break and continue statements. continue and break won’t compile without a label. If label is provided, they will behave as expected. return would exit function where macro is called. If size of the array is 0, element and condition expressions won’t be executed even once and return statement won’t exit the function. This behavior is different from [return; 0] which performs early return regardless.

array![return; 1];
array![break; 1];
array![continue; 1];
'a: loop { array![break 'a; 1]; };
'a: for _ in 0..3 { array![continue 'a; 1]; };

List

For consistency with built-in syntax, arrays may be constructed with a list of expressions.

let values = array![1, 2, 3];

assert_eq!(values, [1, 2, 3]);