Filter a list with macros

Is there a way to filter a long list in a macro? Here is a tt muncher approach:

macro_rules! test {
  (@rec ($($left:tt)*) (keep $t:tt) $($right:tt)*) => {
    test!(@rec ($($left)* $t) $($right)*)
  };
  (@rec ($($left:tt)*) (drop $t:tt) $($right:tt)*) => {
    test!(@rec ($($left)*) $($right)*)
  };
  (@rec ($(($a:expr))*)) => { [$($a),*] };
  ($($x:ident $t:expr,)*) => { test!(@rec () $(($x ($t)))*) }
}

fn main() -> [u8; 4] {
  test! {
    keep 1,
    drop b,
    keep 2,
    keep 3,
    drop a,
    keep 4,
  }
}

This has problems when the list is long though because of the recursion depth. I would like to do something like mapping filter1!(keep $t) -> { $t } and filter1!(drop $t) -> {}, and then do something like test!($($x $t,)*) -> finish!($(filter1!($x $t))*), but I don't know how to make filter1 evaluate instead of getting passed literally to finish. I have seen callback macros used for this, but I don't see how to use them in this case.

macro_rules! test {
    (@inner; $($(keep $($keep:literal)?)? $(drop)?: $t:expr,)*) => {
        [$($($($keep)? $t,)?)*]
    };
    ($($x:ident $t:expr,)*) => {
        test!(@inner; $($x: $t,)*)
    };
}

fn a() -> [u8; 4] {
  test! {
    keep 1,
    drop b,
    keep 2,
    keep 3,
    drop a,
    keep 4,
  }
}
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.