Skip to main content

const_tools/
scan.rs

1/// Produces an array of intermediate fold results in const contexts.
2///
3/// # Examples
4///
5/// ```
6/// use const_tools::scan;
7///
8/// const fn enumerate<T, const N: usize>(value: [T; N]) -> [(usize, T); N] {
9///     scan!(value, 0, |count, item| {
10///         let index = *count;
11///         *count += 1;
12///         (index, item)
13///     })
14/// }
15/// ```
16#[macro_export]
17macro_rules! scan {
18    (zip!($($iae:expr),* $(,)?), $init:expr, |$acc:pat_param, ($($iip:pat_param),* $(,)?)| $body:expr) => {{
19        let mut acc = $init;
20        $crate::map!(zip!($($iae),*), |($($iip,)*)| {
21            let $acc = &mut acc;
22            $body
23        })
24    }};
25    (zip!($($iae:expr),* $(,)?), $init:expr, $fn:expr) => {
26        $crate::__zip_left!(
27            [$(($iae, ))*]
28            [(ii0) (ii1) (ii2) (ii3) (ii4) (ii5) (ii6) (ii7) (ii8) (ii9) (ii10) (ii11)]
29            "unsupported number of inputs"
30            $crate::__scan__zip_function!(<> [$init] [$fn])
31        )
32    };
33    ($iae:expr, $init:expr, |$acc:pat_param, $iip:pat_param| $body:expr) => {{
34        let mut acc = $init;
35        $crate::map!($iae, |$iip| {
36            let $acc = &mut acc;
37            $body
38        })
39    }};
40    ($iae:expr, $init:expr, $fn:expr) => {{
41        let mut acc = $init;
42        $crate::map!($iae, |item| {
43            $fn(&mut acc, item)
44        })
45    }};
46}
47
48#[doc(hidden)]
49#[macro_export]
50macro_rules! __scan__zip_function {
51    ([$(($iae:expr, $ii:ident))*] [$init:expr] [$fn:expr]) => {
52        $crate::scan!(zip!($($iae),*), $init, |acc, ($($ii,)*)| $fn(acc, ($($ii,)*)))
53    };
54}