macro_rules! azip {
    (@build $apply:ident (index $index:pat, $first_pat:pat in $first_prod:expr $(,)?) $body:expr) => { ... };
    (@build $apply:ident (index $index:pat, $first_pat:pat in $first_prod:expr, $($pat:pat in $prod:expr),* $(,)?) $body:expr) => { ... };
    (@build $apply:ident ($first_pat:pat in $first_prod:expr $(,)?) $body:expr) => { ... };
    (@build $apply:ident ($first_pat:pat in $first_prod:expr, $($pat:pat in $prod:expr),* $(,)?) $body:expr) => { ... };
    (@build $apply:ident $first_prod:expr $(, $prod:expr)* $(,)?) => { ... };
    (@build $($t:tt)*) => { ... };
    ($($t:tt)*) => { ... };
Expand description

Array zip macro: lock step function application across several arrays and producers.

This is a shorthand for Zip.

This example:

azip!((a in &mut a, &b in &b, &c in &c) *a = b + c);

Is equivalent to:

Zip::from(&mut a).and(&b).and(&c).for_each(|a, &b, &c| {
    *a = b + c

The syntax is either

azip!(( pat in expr , [ pat in expr ,] ) body_expr )

or, to use Zip::indexed instead of Zip::from,

azip!((index pat , pat in expr , [ pat in expr ,] ) body_expr )

The expr are expressions whose types must implement IntoNdProducer, the pat are the patterns of the parameters to the closure called by Zip::for_each, and body_expr is the body of the closure called by Zip::for_each. You can think of each pat in expr as being analogous to the pat in expr of a normal loop for pat in expr { statements }: a pattern, followed by in, followed by an expression that implements IntoNdProducer (analogous to IntoIterator for a for loop).

Panics if any of the arrays are not of the same shape.


use ndarray::{azip, Array1, Array2, Axis};

type M = Array2<f32>;

// Setup example arrays
let mut a = M::zeros((16, 16));
let mut b = M::zeros(a.dim());
let mut c = M::zeros(a.dim());

// assign values
for ((i, j), elt) in c.indexed_iter_mut() {
    *elt = (i + 10 * j) as f32;

// Example 1: Compute a simple ternary operation:
// elementwise addition of b and c, stored in a
azip!((a in &mut a, &b in &b, &c in &c) *a = b + c);

assert_eq!(a, &b + &c);

// Example 2: azip!() with index
azip!((index (i, j), &b in &b, &c in &c) {
    a[[i, j]] = b - c;

assert_eq!(a, &b - &c);

// Example 3: azip!() on references
// See the definition of the function below
borrow_multiply(&mut a, &b, &c);

assert_eq!(a, &b * &c);

// Since this function borrows its inputs, the `IntoNdProducer`
// expressions don't need to explicitly include `&mut` or `&`.
fn borrow_multiply(a: &mut M, b: &M, c: &M) {
    azip!((a in a, &b in b, &c in c) *a = b * c);

// Example 4: using azip!() without dereference in pattern.
// Create a new array `totals` with one entry per row of `a`.
// Use azip to traverse the rows of `a` and assign to the corresponding
// entry in `totals` with the sum across each row.
// The row is an array view; it doesn't need to be dereferenced.
let mut totals = Array1::zeros(a.nrows());
azip!((totals in &mut totals, row in a.rows()) *totals = row.sum());

// Check the result against the built in `.sum_axis()` along axis 1.
assert_eq!(totals, a.sum_axis(Axis(1)));