1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#[macro_export]
macro_rules! par_izip {
    // Define the closure for flattening the tuple in a map call for parallel processing.
    ( @closure $p:pat => $tup:expr ) => {
        |$p| $tup
    };

    ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
        par_izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
    };

    // Unary case: Convert a single iterable into a parallel iterator.
    ($first:expr $(,)*) => {
        rayon::prelude::IntoParallelRefIterator::par_iter(&$first)
    };

    // Binary case: Zip two parallel iterators.
    ($first:expr, $second:expr $(,)*) => {
        par_izip!($first)
            .zip($second)
    };

    // N-ary case: Zip multiple parallel iterators and flatten the tuple.
    ( $first:expr $( , $rest:expr )* $(,)* ) => {
        par_izip!($first)
            $(
                .zip($rest)
            )*
            .map(
                par_izip!(@closure a => (a) $( , $rest )*)
            )
    };
}

#[cfg(test)]
mod tests {
    use rayon::prelude::*;

    #[test]
    fn try_it() {
        let v = par_izip!(vec![1, 2, 3], vec![1, 2, 3], vec![1, 2, 3])
            .map(|(a, b, c)| {
                println!("{a}, {b}, {c}");
                a + b + c
            })
            .collect::<Vec<_>>();
        println!("{v:?}");
    }
}